Coverage Report

Created: 2025-07-12 06:58

/src/libmpeg2/common/ideint_utils.c
Line
Count
Source (jump to first uncovered line)
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
* @file
23
*  ideint_utils.c
24
*
25
* @brief
26
*  This file contains the definitions of the core  processing of the de
27
* interlacer.
28
*
29
* @author
30
*  Ittiam
31
*
32
* @par List of Functions:
33
*  ideint_weave_pic()
34
*  init_bob_indices()
35
*  ideint_weave_blk()
36
*  ideint_spatial_filter()
37
*
38
* @remarks
39
*  None
40
*
41
*******************************************************************************
42
*/
43
/*****************************************************************************/
44
/* File Includes                                                             */
45
/*****************************************************************************/
46
/* System include files */
47
#include <stdio.h>
48
#include <stdint.h>
49
#include <string.h>
50
#include <stdlib.h>
51
#include <assert.h>
52
53
54
/* User include files */
55
#include "icv_datatypes.h"
56
#include "icv_macros.h"
57
#include "icv_platform_macros.h"
58
#include "icv.h"
59
#include "icv_variance.h"
60
#include "icv_sad.h"
61
#include "ideint.h"
62
#include "ideint_defs.h"
63
#include "ideint_structs.h"
64
#include "ideint_utils.h"
65
#include "ideint_cac.h"
66
67
/**
68
*******************************************************************************
69
*
70
* @brief
71
*  Weaves two fields to produce a frame
72
*
73
* @par   Description
74
*  Weaves two fields to produce a frame
75
*
76
* @param[in] ps_src_top
77
*  Top field source
78
*
79
* @param[in] ps_src_bot
80
*  Bottom field source
81
*
82
* @param[in] ps_dst_frm
83
*  Destination frame
84
*
85
* @returns
86
*   0 on Success
87
*
88
* @remarks
89
*
90
*******************************************************************************
91
*/
92
WORD32 ideint_weave_pic(icv_pic_t *ps_src_top,
93
                        icv_pic_t *ps_src_bot,
94
                        icv_pic_t *ps_dst_frm,
95
                        WORD32 start_row,
96
                        WORD32 num_rows)
97
0
{
98
0
    UWORD8 *pu1_src, *pu1_dst;
99
0
    WORD32 i, j, num_comp;
100
0
    icv_pic_t *ps_src_fld;
101
0
    WORD32 fld;
102
0
    icv_pic_t *ps_src_flds[2];
103
104
0
    num_comp = 3;
105
0
    ps_src_flds[0] = ps_src_top;
106
0
    ps_src_flds[1] = ps_src_bot;
107
108
0
    for(fld = 0; fld < 2; fld++)
109
0
    {
110
0
        ps_src_fld = ps_src_flds[fld];
111
0
        for(i = 0; i < num_comp; i++)
112
0
        {
113
0
            WORD32 src_strd;
114
0
            WORD32 dst_strd;
115
0
            WORD32 comp_row_start, comp_row_end;
116
0
            comp_row_start = start_row;
117
0
            comp_row_end = comp_row_start + num_rows;
118
0
            if(i)
119
0
            {
120
0
                comp_row_start >>= 1;
121
0
                comp_row_end >>= 1;
122
0
            }
123
124
0
            comp_row_end = MIN(comp_row_end, ps_dst_frm->ai4_ht[i]);
125
126
0
            pu1_src = ps_src_fld->apu1_buf[i];
127
0
            pu1_dst = ps_dst_frm->apu1_buf[i];
128
129
0
            src_strd = ps_src_fld->ai4_strd[i];
130
0
            dst_strd = ps_dst_frm->ai4_strd[i];
131
132
            /* If source field is bottom, increment destination */
133
0
            pu1_dst += fld * dst_strd;
134
135
            /* In case input and output are pointing to same buffer, then no need to copy */
136
0
            if((pu1_src != pu1_dst) || ((2 * dst_strd) != src_strd))
137
0
            {
138
0
                pu1_dst += ps_dst_frm->ai4_strd[i] * comp_row_start;
139
0
                pu1_src += ps_src_fld->ai4_strd[i] * comp_row_start / 2;
140
141
0
                for(j = comp_row_start; j < comp_row_end; j += 2)
142
0
                {
143
0
                    memcpy(pu1_dst, pu1_src, ps_dst_frm->ai4_wd[i]);
144
0
                    pu1_dst += ps_dst_frm->ai4_strd[i] * 2;
145
0
                    pu1_src += ps_src_fld->ai4_strd[i];
146
0
                }
147
0
            }
148
0
        }
149
0
    }
150
0
    return 0;
151
0
}
152
153
154
/**
155
*******************************************************************************
156
*
157
* @brief
158
*  Weaves a 8x8 block
159
*
160
* @par   Description
161
*  Weaves a 8x8 block from two fields
162
*
163
* @param[in] pu1_top
164
*  Top field source
165
*
166
* @param[in] pu1_bot
167
*  Bottom field source
168
*
169
* @param[in] pu1_dst
170
*  Destination
171
*
172
* @param[in] dst_strd
173
*  Destination stride
174
*
175
* @param[in] src_strd
176
*  Source stride
177
*
178
* @returns
179
*  0 on success
180
*
181
* @remarks
182
*
183
*******************************************************************************
184
*/
185
WORD32 ideint_weave_blk(UWORD8 *pu1_top,
186
                        UWORD8 *pu1_bot,
187
                        UWORD8 *pu1_dst,
188
                        WORD32 dst_strd,
189
                        WORD32 src_strd,
190
                        WORD32 wd,
191
                        WORD32 ht)
192
107M
{
193
107M
    WORD32 j;
194
195
526M
    for(j = 0; j < ht; j += 2)
196
419M
    {
197
419M
        memcpy(pu1_dst, pu1_top, wd);
198
419M
        pu1_dst += dst_strd;
199
419M
        pu1_top += src_strd;
200
201
419M
        memcpy(pu1_dst, pu1_bot, wd);
202
419M
        pu1_dst += dst_strd;
203
419M
        pu1_bot += src_strd;
204
419M
    }
205
107M
    return 0;
206
107M
}
207
208
/**
209
*******************************************************************************
210
*
211
* @brief
212
*  Copy a boundary block and pad
213
*
214
* @par   Description
215
*  Copies a block on one of the boundaries and pads
216
*
217
* @param[in] pu1_top
218
*  Top field source
219
*
220
* @param[in] pu1_bot
221
*  Bottom field source
222
*
223
* @param[in] pu1_pad
224
*  Padded destination
225
*
226
* @param[in] cur_strd
227
*  Stride for pu1_top and pu1_bot
228
*
229
* @param[in] row
230
*  Current block's row
231
*
232
* @param[in] col
233
*  Current block's column
234
*
235
* @param[in] num_blks_y
236
*  Number of blocks in Y direction
237
*
238
* @param[in] num_blks_x
239
*  Number of blocks in X direction
240
241
* @returns
242
*  None
243
*
244
* @remarks
245
*
246
*******************************************************************************
247
*/
248
void ideint_pad_blk(UWORD8 *pu1_top,
249
                    UWORD8 *pu1_bot,
250
                    UWORD8 *pu1_pad,
251
                    WORD32 cur_strd,
252
                    WORD32 row,
253
                    WORD32 col,
254
                    WORD32 num_blks_y,
255
                    WORD32 num_blks_x,
256
                    WORD32 blk_wd,
257
                    WORD32 blk_ht)
258
3.92M
{
259
3.92M
    WORD32 i;
260
3.92M
    WORD32 num_cols, num_rows;
261
3.92M
    UWORD8 *pu1_dst;
262
3.92M
    UWORD8 *pu1_src_top;
263
3.92M
    UWORD8 *pu1_src_bot;
264
265
3.92M
    num_rows = blk_ht + 4;
266
3.92M
    num_cols = blk_wd + 4;
267
268
3.92M
    pu1_src_top = pu1_top - cur_strd - 2;
269
3.92M
    pu1_src_bot = pu1_bot - cur_strd - 2;
270
3.92M
    pu1_dst = pu1_pad;
271
272
3.92M
    if(0 == col)
273
986k
    {
274
986k
        num_cols -= 2;
275
986k
        pu1_dst += 2;
276
986k
        pu1_src_top += 2;
277
986k
        pu1_src_bot += 2;
278
986k
    }
279
280
3.92M
    if(0 == row)
281
902k
    {
282
902k
        num_rows -= 2;
283
902k
        pu1_dst += 2 * (BLK_WD + 4);
284
902k
        pu1_src_top += cur_strd;
285
902k
        pu1_src_bot += cur_strd;
286
902k
    }
287
288
3.92M
    if((num_blks_x - 1) == col)
289
1.05M
        num_cols -= 2;
290
291
3.92M
    if((num_blks_y - 1) == row)
292
1.10M
        num_rows -= 2;
293
294
23.8M
    for(i = 0; i < num_rows; i += 2)
295
19.9M
    {
296
19.9M
        memcpy(pu1_dst, pu1_src_top, num_cols);
297
19.9M
        pu1_dst += (BLK_WD + 4);
298
299
19.9M
        memcpy(pu1_dst, pu1_src_bot, num_cols);
300
19.9M
        pu1_dst += (BLK_WD + 4);
301
302
19.9M
        pu1_src_top += cur_strd;
303
19.9M
        pu1_src_bot += cur_strd;
304
19.9M
    }
305
306
307
    /* Pad Left */
308
3.92M
    if(0 == col)
309
989k
    {
310
12.7M
       for(i = 0; i < (BLK_HT + 4); i++)
311
11.8M
       {
312
11.8M
           WORD32 ofst = i * (BLK_WD + 4) + 2;
313
11.8M
           pu1_pad[ofst - 1] = pu1_pad[ofst];
314
11.8M
           pu1_pad[ofst - 2] = pu1_pad[ofst];
315
11.8M
       }
316
989k
    }
317
318
    /* Pad right */
319
3.92M
    if((num_blks_x - 1) == col)
320
1.05M
    {
321
13.6M
       for(i = 0; i < (BLK_HT + 4); i++)
322
12.6M
       {
323
12.6M
           WORD32 ofst =  i * (BLK_WD + 4) + 2 + blk_wd - 1;
324
12.6M
           WORD32 size = (BLK_WD - blk_wd) + 2;
325
           /* Padding on right should include padding for boundary
326
            * blocks when width is non-multiple of 8
327
            */
328
12.6M
           memset(&pu1_pad[ofst + 1], pu1_pad[ofst], size);
329
12.6M
       }
330
1.05M
    }
331
332
    /* Pad Top */
333
3.92M
    if(0 == row)
334
902k
    {
335
902k
        WORD32 src_ofst = 2 * (BLK_WD + 4);
336
902k
        WORD32 dst_ofst = 0;
337
902k
        memcpy(pu1_pad + dst_ofst, pu1_pad + src_ofst, (BLK_WD + 4));
338
902k
        src_ofst += (BLK_WD + 4);
339
902k
        dst_ofst += (BLK_WD + 4);
340
902k
        memcpy(pu1_pad + dst_ofst, pu1_pad + src_ofst, (BLK_WD + 4));
341
902k
    }
342
343
    /* Pad Bottom */
344
3.92M
    if((num_blks_y - 1) == row)
345
1.10M
    {
346
1.10M
        WORD32 src_ofst = (0 + blk_ht) * (BLK_WD + 4);
347
1.10M
        WORD32 dst_ofst = (1 + blk_ht) * (BLK_WD + 4);
348
1.10M
        WORD32 size = (BLK_HT - blk_ht) + 2;
349
350
        /* Padding on bottom should include padding for boundary
351
         * blocks when height is non-multiple of 8
352
         */
353
6.93M
        for(i = 0; i < size; i++)
354
5.82M
        {
355
5.82M
            memcpy(pu1_pad + dst_ofst, pu1_pad + src_ofst, (BLK_WD + 4));
356
5.82M
            dst_ofst += (BLK_WD + 4);
357
5.82M
        }
358
1.10M
    }
359
3.92M
}
360
361
/**
362
*******************************************************************************
363
*
364
* @brief
365
*  Performs spatial edge adaptive filtering
366
*
367
* @par   Description
368
*  Performs spatial edge adaptive filtering by detecting edge direction
369
*
370
* @param[in] pu1_src
371
*  Source buffer
372
*
373
* @param[in] pu1_out
374
*  Destination buffer
375
*
376
* @param[in] src_strd
377
*  Source stride
378
*
379
* @param[in] out_strd
380
*  Destination stride
381
382
* @returns
383
* None
384
*
385
* @remarks
386
*
387
*******************************************************************************
388
*/
389
void ideint_spatial_filter(UWORD8 *pu1_src,
390
                           UWORD8 *pu1_out,
391
                           WORD32 src_strd,
392
                           WORD32 out_strd)
393
17.0M
{
394
17.0M
    WORD32 i;
395
17.0M
    WORD32 j;
396
17.0M
    WORD32 k;
397
398
    /*********************************************************************/
399
    /* This loop is for the two halves inside the 8x4 block.             */
400
    /*********************************************************************/
401
48.4M
    for(k = 0; k < 2; k++)
402
31.3M
    {
403
31.3M
        WORD32 adiff[3] = {0, 0, 0};
404
31.3M
        WORD32 shift;
405
31.3M
        WORD32 dir_45_le_90, dir_45_le_135, dir_135_le_90;
406
31.3M
        UWORD8 *pu1_row_1, *pu1_row_2, *pu1_dst;
407
408
        /*****************************************************************/
409
        /* Direction detection                                           */
410
        /*****************************************************************/
411
31.3M
        pu1_row_1 = pu1_src;
412
31.3M
        pu1_row_2 = pu1_src + src_strd;
413
414
        /*****************************************************************/
415
        /* Calculating the difference along each of the 3 directions.    */
416
        /*****************************************************************/
417
137M
        for(j = 0; j < SUB_BLK_HT; j ++)
418
106M
        {
419
528M
            for(i = 0; i < SUB_BLK_WD; i++)
420
422M
            {
421
422M
                adiff[0] += ABS_DIF(pu1_row_1[i], pu1_row_2[i]); /*  90 */
422
423
422M
                adiff[1] += ABS_DIF(pu1_row_1[i - 1], pu1_row_2[i + 1]); /* 135 */
424
425
422M
                adiff[2] += ABS_DIF(pu1_row_1[i + 1], pu1_row_2[i - 1]); /*  45 */
426
422M
            }
427
106M
            pu1_row_1 += src_strd;
428
106M
            pu1_row_2 += src_strd;
429
106M
        }
430
431
        /*****************************************************************/
432
        /* Applying bias, to make the diff comparision more robust.      */
433
        /*****************************************************************/
434
31.3M
        adiff[0] *= EDGE_BIAS_0;
435
31.3M
        adiff[1] *= EDGE_BIAS_1;
436
31.3M
        adiff[2] *= EDGE_BIAS_1;
437
438
        /*****************************************************************/
439
        /* comapring the diffs */
440
        /*****************************************************************/
441
31.3M
        dir_45_le_90  = (adiff[2] <= adiff[0]);
442
31.3M
        dir_45_le_135 = (adiff[2] <= adiff[1]);
443
31.3M
        dir_135_le_90 = (adiff[1] <= adiff[0]);
444
445
        /*****************************************************************/
446
        /* Direction selection. */
447
        /*****************************************************************/
448
31.3M
        shift = 0;
449
31.3M
        if(1 == dir_45_le_135)
450
28.5M
        {
451
28.5M
            if(1 == dir_45_le_90)
452
28.0M
                shift = 1;
453
28.5M
        }
454
2.85M
        else
455
2.85M
        {
456
2.85M
            if(1 == dir_135_le_90)
457
22.5k
                shift = -1;
458
2.85M
        }
459
460
        /*****************************************************************/
461
        /* Directional interpolation */
462
        /*****************************************************************/
463
31.3M
        pu1_row_1 = pu1_src + shift;
464
31.3M
        pu1_row_2 = pu1_src + src_strd - shift;
465
31.3M
        pu1_dst   = pu1_out;
466
467
142M
        for(j = 0; j < SUB_BLK_HT; j++)
468
111M
        {
469
537M
            for(i = 0; i < SUB_BLK_WD; i++)
470
426M
            {
471
426M
                pu1_dst[i] = (UWORD8)AVG(pu1_row_1[i], pu1_row_2[i]);
472
426M
            }
473
111M
            pu1_row_1 += src_strd;
474
111M
            pu1_row_2 += src_strd;
475
111M
            pu1_dst   += out_strd;
476
111M
        }
477
478
31.3M
        pu1_out += SUB_BLK_WD;
479
31.3M
        pu1_src += SUB_BLK_WD;
480
31.3M
    }
481
17.0M
}
482