Home | History | Annotate | Download | only in lvpp
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "VideoEditorTools.h"
     18 #include "PreviewRenderer.h"
     19 /*+ Handle the image files here */
     20 #include <utils/Log.h>
     21 /*- Handle the image files here */
     22 
     23 const M4VIFI_UInt8   M4VIFI_ClipTable[1256]
     24 = {
     25 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     26 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     27 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     28 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     29 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     30 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     31 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     32 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     34 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     35 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     36 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     39 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     40 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     41 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     43 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     45 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     54 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     55 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     87 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
     88 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
     89 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
     90 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
     91 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
     92 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
     93 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
     94 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
     95 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43,
     96 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
     97 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53,
     98 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b,
     99 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63,
    100 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
    101 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73,
    102 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b,
    103 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
    104 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b,
    105 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93,
    106 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
    107 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3,
    108 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
    109 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
    110 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb,
    111 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3,
    112 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb,
    113 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3,
    114 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb,
    115 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3,
    116 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
    117 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3,
    118 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
    119 0xfc, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
    120 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    121 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    122 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    123 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    124 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    125 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    126 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    127 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    128 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    129 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    130 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    131 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    132 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    133 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    134 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    135 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    136 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    137 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    138 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    139 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    140 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    141 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    142 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    143 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    144 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    145 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    146 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    147 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    148 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    149 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    150 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    151 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    152 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    153 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    154 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    155 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    156 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    157 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    158 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    159 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    160 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    161 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    162 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    163 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    164 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    165 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    166 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    167 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    168 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    169 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    170 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    171 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    172 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    173 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    174 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    175 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    176 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    177 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    178 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    179 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    180 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    181 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
    182 };
    183 
    184 /* Division table for ( 65535/x ); x = 0 to 512 */
    185 const M4VIFI_UInt16  M4VIFI_DivTable[512]
    186 = {
    187 0, 65535, 32768, 21845, 16384, 13107, 10922, 9362,
    188 8192, 7281, 6553, 5957, 5461, 5041, 4681, 4369,
    189 4096, 3855, 3640, 3449, 3276, 3120, 2978, 2849,
    190 2730, 2621, 2520, 2427, 2340, 2259, 2184, 2114,
    191 2048, 1985, 1927, 1872, 1820, 1771, 1724, 1680,
    192 1638, 1598, 1560, 1524, 1489, 1456, 1424, 1394,
    193 1365, 1337, 1310, 1285, 1260, 1236, 1213, 1191,
    194 1170, 1149, 1129, 1110, 1092, 1074, 1057, 1040,
    195 1024, 1008, 992, 978, 963, 949, 936, 923,
    196 910, 897, 885, 873, 862, 851, 840, 829,
    197 819, 809, 799, 789, 780, 771, 762, 753,
    198 744, 736, 728, 720, 712, 704, 697, 689,
    199 682, 675, 668, 661, 655, 648, 642, 636,
    200 630, 624, 618, 612, 606, 601, 595, 590,
    201 585, 579, 574, 569, 564, 560, 555, 550,
    202 546, 541, 537, 532, 528, 524, 520, 516,
    203 512, 508, 504, 500, 496, 492, 489, 485,
    204 481, 478, 474, 471, 468, 464, 461, 458,
    205 455, 451, 448, 445, 442, 439, 436, 434,
    206 431, 428, 425, 422, 420, 417, 414, 412,
    207 409, 407, 404, 402, 399, 397, 394, 392,
    208 390, 387, 385, 383, 381, 378, 376, 374,
    209 372, 370, 368, 366, 364, 362, 360, 358,
    210 356, 354, 352, 350, 348, 346, 344, 343,
    211 341, 339, 337, 336, 334, 332, 330, 329,
    212 327, 326, 324, 322, 321, 319, 318, 316,
    213 315, 313, 312, 310, 309, 307, 306, 304,
    214 303, 302, 300, 299, 297, 296, 295, 293,
    215 292, 291, 289, 288, 287, 286, 284, 283,
    216 282, 281, 280, 278, 277, 276, 275, 274,
    217 273, 271, 270, 269, 268, 267, 266, 265,
    218 264, 263, 262, 261, 260, 259, 258, 257,
    219 256, 255, 254, 253, 252, 251, 250, 249,
    220 248, 247, 246, 245, 244, 243, 242, 241,
    221 240, 240, 239, 238, 237, 236, 235, 234,
    222 234, 233, 232, 231, 230, 229, 229, 228,
    223 227, 226, 225, 225, 224, 223, 222, 222,
    224 221, 220, 219, 219, 218, 217, 217, 216,
    225 215, 214, 214, 213, 212, 212, 211, 210,
    226 210, 209, 208, 208, 207, 206, 206, 205,
    227 204, 204, 203, 202, 202, 201, 201, 200,
    228 199, 199, 198, 197, 197, 196, 196, 195,
    229 195, 194, 193, 193, 192, 192, 191, 191,
    230 190, 189, 189, 188, 188, 187, 187, 186,
    231 186, 185, 185, 184, 184, 183, 183, 182,
    232 182, 181, 181, 180, 180, 179, 179, 178,
    233 178, 177, 177, 176, 176, 175, 175, 174,
    234 174, 173, 173, 172, 172, 172, 171, 171,
    235 170, 170, 169, 169, 168, 168, 168, 167,
    236 167, 166, 166, 165, 165, 165, 164, 164,
    237 163, 163, 163, 162, 162, 161, 161, 161,
    238 160, 160, 159, 159, 159, 158, 158, 157,
    239 157, 157, 156, 156, 156, 155, 155, 154,
    240 154, 154, 153, 153, 153, 152, 152, 152,
    241 151, 151, 151, 150, 150, 149, 149, 149,
    242 148, 148, 148, 147, 147, 147, 146, 146,
    243 146, 145, 145, 145, 144, 144, 144, 144,
    244 143, 143, 143, 142, 142, 142, 141, 141,
    245 141, 140, 140, 140, 140, 139, 139, 139,
    246 138, 138, 138, 137, 137, 137, 137, 136,
    247 136, 136, 135, 135, 135, 135, 134, 134,
    248 134, 134, 133, 133, 133, 132, 132, 132,
    249 132, 131, 131, 131, 131, 130, 130, 130,
    250 130, 129, 129, 129, 129, 128, 128, 128
    251 };
    252 
    253 const M4VIFI_Int32  const_storage1[8]
    254 = {
    255 0x00002568, 0x00003343,0x00000649,0x00000d0f, 0x0000D86C, 0x0000D83B, 0x00010000, 0x00010000
    256 };
    257 
    258 const M4VIFI_Int32  const_storage[8]
    259 = {
    260 0x00002568, 0x00003343, 0x1BF800, 0x00000649, 0x00000d0f, 0x110180, 0x40cf, 0x22BE00
    261 };
    262 
    263 
    264 const M4VIFI_UInt16  *M4VIFI_DivTable_zero
    265  = &M4VIFI_DivTable[0];
    266 
    267 const M4VIFI_UInt8   *M4VIFI_ClipTable_zero
    268  = &M4VIFI_ClipTable[500];
    269 
    270 M4VIFI_UInt8 M4VIFI_YUV420PlanarToYUV420Semiplanar(void *user_data,
    271     M4VIFI_ImagePlane *PlaneIn, M4VIFI_ImagePlane *PlaneOut ) {
    272 
    273     M4VIFI_UInt32 i;
    274     M4VIFI_UInt8 *p_buf_src, *p_buf_dest, *p_buf_src_u, *p_buf_src_v;
    275     M4VIFI_UInt8    return_code = M4VIFI_OK;
    276 
    277     /* the filter is implemented with the assumption that the width is equal to stride */
    278     if(PlaneIn[0].u_width != PlaneIn[0].u_stride)
    279         return M4VIFI_INVALID_PARAM;
    280 
    281     /* The input Y Plane is the same as the output Y Plane */
    282     p_buf_src = &(PlaneIn[0].pac_data[PlaneIn[0].u_topleft]);
    283     p_buf_dest = &(PlaneOut[0].pac_data[PlaneOut[0].u_topleft]);
    284     memcpy((void *)p_buf_dest,(void *)p_buf_src ,
    285         PlaneOut[0].u_width * PlaneOut[0].u_height);
    286 
    287     /* The U and V components are planar. The need to be made interleaved */
    288     p_buf_src_u = &(PlaneIn[1].pac_data[PlaneIn[1].u_topleft]);
    289     p_buf_src_v = &(PlaneIn[2].pac_data[PlaneIn[2].u_topleft]);
    290     p_buf_dest  = &(PlaneOut[1].pac_data[PlaneOut[1].u_topleft]);
    291 
    292     for(i = 0; i < PlaneOut[1].u_width*PlaneOut[1].u_height; i++)
    293     {
    294         *p_buf_dest++ = *p_buf_src_u++;
    295         *p_buf_dest++ = *p_buf_src_v++;
    296     }
    297     return return_code;
    298 }
    299 
    300 M4VIFI_UInt8 M4VIFI_SemiplanarYUV420toYUV420(void *user_data,
    301     M4VIFI_ImagePlane *PlaneIn, M4VIFI_ImagePlane *PlaneOut ) {
    302 
    303      M4VIFI_UInt32 i;
    304      M4VIFI_UInt8 *p_buf_src, *p_buf_dest, *p_buf_src_u, *p_buf_src_v;
    305      M4VIFI_UInt8 *p_buf_dest_u,*p_buf_dest_v,*p_buf_src_uv;
    306      M4VIFI_UInt8     return_code = M4VIFI_OK;
    307 
    308      /* the filter is implemented with the assumption that the width is equal to stride */
    309      if(PlaneIn[0].u_width != PlaneIn[0].u_stride)
    310         return M4VIFI_INVALID_PARAM;
    311 
    312      /* The input Y Plane is the same as the output Y Plane */
    313      p_buf_src = &(PlaneIn[0].pac_data[PlaneIn[0].u_topleft]);
    314      p_buf_dest = &(PlaneOut[0].pac_data[PlaneOut[0].u_topleft]);
    315      memcpy((void *)p_buf_dest,(void *)p_buf_src ,
    316          PlaneOut[0].u_width * PlaneOut[0].u_height);
    317 
    318      /* The U and V components are planar. The need to be made interleaved */
    319      p_buf_src_uv = &(PlaneIn[1].pac_data[PlaneIn[1].u_topleft]);
    320      p_buf_dest_u  = &(PlaneOut[1].pac_data[PlaneOut[1].u_topleft]);
    321      p_buf_dest_v  = &(PlaneOut[2].pac_data[PlaneOut[2].u_topleft]);
    322 
    323      for(i = 0; i < PlaneOut[1].u_width*PlaneOut[1].u_height; i++)
    324      {
    325         *p_buf_dest_u++ = *p_buf_src_uv++;
    326         *p_buf_dest_v++ = *p_buf_src_uv++;
    327      }
    328      return return_code;
    329 }
    330 
    331 
    332 /**
    333  ******************************************************************************
    334  * prototype    M4VSS3GPP_externalVideoEffectColor(M4OSA_Void *pFunctionContext,
    335  *                                                  M4VIFI_ImagePlane *PlaneIn,
    336  *                                                  M4VIFI_ImagePlane *PlaneOut,
    337  *                                                  M4VSS3GPP_ExternalProgress *pProgress,
    338  *                                                  M4OSA_UInt32 uiEffectKind)
    339  *
    340  * @brief   This function apply a color effect on an input YUV420 planar frame
    341  * @note
    342  * @param   pFunctionContext(IN) Contains which color to apply (not very clean ...)
    343  * @param   PlaneIn         (IN) Input YUV420 planar
    344  * @param   PlaneOut        (IN/OUT) Output YUV420 planar
    345  * @param   pProgress       (IN/OUT) Progress indication (0-100)
    346  * @param   uiEffectKind    (IN) Unused
    347  *
    348  * @return  M4VIFI_OK:  No error
    349  ******************************************************************************
    350 */
    351 M4OSA_ERR M4VSS3GPP_externalVideoEffectColor(M4OSA_Void *pFunctionContext,
    352             M4VIFI_ImagePlane *PlaneIn, M4VIFI_ImagePlane *PlaneOut,
    353             M4VSS3GPP_ExternalProgress *pProgress, M4OSA_UInt32 uiEffectKind) {
    354 
    355     M4VIFI_Int32 plane_number;
    356     M4VIFI_UInt32 i,j;
    357     M4VIFI_UInt8 *p_buf_src, *p_buf_dest;
    358     M4xVSS_ColorStruct* ColorContext = (M4xVSS_ColorStruct*)pFunctionContext;
    359 
    360     for (plane_number = 0; plane_number < 3; plane_number++)
    361     {
    362         p_buf_src =
    363          &(PlaneIn[plane_number].pac_data[PlaneIn[plane_number].u_topleft]);
    364 
    365         p_buf_dest =
    366          &(PlaneOut[plane_number].pac_data[PlaneOut[plane_number].u_topleft]);
    367         for (i = 0; i < PlaneOut[plane_number].u_height; i++)
    368         {
    369             /**
    370              * Chrominance */
    371             if(plane_number==1 || plane_number==2)
    372             {
    373                 //switch ((M4OSA_UInt32)pFunctionContext) // commented because a structure for the effects context exist
    374                 switch (ColorContext->colorEffectType)
    375                 {
    376                 case M4xVSS_kVideoEffectType_BlackAndWhite:
    377                     memset((void *)p_buf_dest,128,
    378                      PlaneIn[plane_number].u_width);
    379                     break;
    380                 case M4xVSS_kVideoEffectType_Pink:
    381                     memset((void *)p_buf_dest,255,
    382                      PlaneIn[plane_number].u_width);
    383                     break;
    384                 case M4xVSS_kVideoEffectType_Green:
    385                     memset((void *)p_buf_dest,0,
    386                      PlaneIn[plane_number].u_width);
    387                     break;
    388                 case M4xVSS_kVideoEffectType_Sepia:
    389                     if(plane_number==1)
    390                     {
    391                         memset((void *)p_buf_dest,117,
    392                          PlaneIn[plane_number].u_width);
    393                     }
    394                     else
    395                     {
    396                         memset((void *)p_buf_dest,139,
    397                          PlaneIn[plane_number].u_width);
    398                     }
    399                     break;
    400                 case M4xVSS_kVideoEffectType_Negative:
    401                     memcpy((void *)p_buf_dest,
    402                      (void *)p_buf_src ,PlaneOut[plane_number].u_width);
    403                     break;
    404 
    405                 case M4xVSS_kVideoEffectType_ColorRGB16:
    406                     {
    407                         M4OSA_UInt16 r = 0,g = 0,b = 0,y = 0,u = 0,v = 0;
    408 
    409                         /*first get the r, g, b*/
    410                         b = (ColorContext->rgb16ColorData &  0x001f);
    411                         g = (ColorContext->rgb16ColorData &  0x07e0)>>5;
    412                         r = (ColorContext->rgb16ColorData &  0xf800)>>11;
    413 
    414                         /*keep y, but replace u and v*/
    415                         if(plane_number==1)
    416                         {
    417                             /*then convert to u*/
    418                             u = U16(r, g, b);
    419                             memset((void *)p_buf_dest,(M4OSA_UInt8)u,
    420                              PlaneIn[plane_number].u_width);
    421                         }
    422                         if(plane_number==2)
    423                         {
    424                             /*then convert to v*/
    425                             v = V16(r, g, b);
    426                             memset((void *)p_buf_dest,(M4OSA_UInt8)v,
    427                              PlaneIn[plane_number].u_width);
    428                         }
    429                     }
    430                     break;
    431                 case M4xVSS_kVideoEffectType_Gradient:
    432                     {
    433                         M4OSA_UInt16 r = 0,g = 0,b = 0,y = 0,u = 0,v = 0;
    434 
    435                         /*first get the r, g, b*/
    436                         b = (ColorContext->rgb16ColorData &  0x001f);
    437                         g = (ColorContext->rgb16ColorData &  0x07e0)>>5;
    438                         r = (ColorContext->rgb16ColorData &  0xf800)>>11;
    439 
    440                         /*for color gradation*/
    441                         b = (M4OSA_UInt16)( b - ((b*i)/PlaneIn[plane_number].u_height));
    442                         g = (M4OSA_UInt16)(g - ((g*i)/PlaneIn[plane_number].u_height));
    443                         r = (M4OSA_UInt16)(r - ((r*i)/PlaneIn[plane_number].u_height));
    444 
    445                         /*keep y, but replace u and v*/
    446                         if(plane_number==1)
    447                         {
    448                             /*then convert to u*/
    449                             u = U16(r, g, b);
    450                             memset((void *)p_buf_dest,(M4OSA_UInt8)u,
    451                              PlaneIn[plane_number].u_width);
    452                         }
    453                         if(plane_number==2)
    454                         {
    455                             /*then convert to v*/
    456                             v = V16(r, g, b);
    457                             memset((void *)p_buf_dest,(M4OSA_UInt8)v,
    458                              PlaneIn[plane_number].u_width);
    459                         }
    460                     }
    461                     break;
    462                 default:
    463                     return M4VIFI_INVALID_PARAM;
    464                 }
    465             }
    466             /**
    467              * Luminance */
    468             else
    469             {
    470                 //switch ((M4OSA_UInt32)pFunctionContext)// commented because a structure for the effects context exist
    471                 switch (ColorContext->colorEffectType)
    472                 {
    473                 case M4xVSS_kVideoEffectType_Negative:
    474                     for(j=0;j<PlaneOut[plane_number].u_width;j++)
    475                     {
    476                             p_buf_dest[j] = 255 - p_buf_src[j];
    477                     }
    478                     break;
    479                 default:
    480                     memcpy((void *)p_buf_dest,
    481                      (void *)p_buf_src ,PlaneOut[plane_number].u_width);
    482                     break;
    483                 }
    484             }
    485             p_buf_src += PlaneIn[plane_number].u_stride;
    486             p_buf_dest += PlaneOut[plane_number].u_stride;
    487         }
    488     }
    489 
    490     return M4VIFI_OK;
    491 }
    492 
    493 /**
    494  ******************************************************************************
    495  * prototype    M4VSS3GPP_externalVideoEffectFraming(M4OSA_Void *pFunctionContext,
    496  *                                                  M4VIFI_ImagePlane *PlaneIn,
    497  *                                                  M4VIFI_ImagePlane *PlaneOut,
    498  *                                                  M4VSS3GPP_ExternalProgress *pProgress,
    499  *                                                  M4OSA_UInt32 uiEffectKind)
    500  *
    501  * @brief   This function add a fixed or animated image on an input YUV420 planar frame
    502  * @note
    503  * @param   pFunctionContext(IN) Contains which color to apply (not very clean ...)
    504  * @param   PlaneIn         (IN) Input YUV420 planar
    505  * @param   PlaneOut        (IN/OUT) Output YUV420 planar
    506  * @param   pProgress       (IN/OUT) Progress indication (0-100)
    507  * @param   uiEffectKind    (IN) Unused
    508  *
    509  * @return  M4VIFI_OK:  No error
    510  ******************************************************************************
    511 */
    512 M4OSA_ERR M4VSS3GPP_externalVideoEffectFraming(
    513             M4OSA_Void *userData, M4VIFI_ImagePlane PlaneIn[3],
    514             M4VIFI_ImagePlane *PlaneOut, M4VSS3GPP_ExternalProgress *pProgress,
    515             M4OSA_UInt32 uiEffectKind ) {
    516 
    517     M4VIFI_UInt32 x,y;
    518 
    519     M4VIFI_UInt8 *p_in_Y = PlaneIn[0].pac_data;
    520     M4VIFI_UInt8 *p_in_U = PlaneIn[1].pac_data;
    521     M4VIFI_UInt8 *p_in_V = PlaneIn[2].pac_data;
    522 
    523     M4xVSS_FramingStruct* Framing = M4OSA_NULL;
    524     M4xVSS_FramingStruct* currentFraming = M4OSA_NULL;
    525     M4VIFI_UInt8 *FramingRGB = M4OSA_NULL;
    526 
    527     M4VIFI_UInt8 *p_out0;
    528     M4VIFI_UInt8 *p_out1;
    529     M4VIFI_UInt8 *p_out2;
    530 
    531     M4VIFI_UInt32 topleft[2];
    532 
    533     M4OSA_UInt8 transparent1 =
    534      (M4OSA_UInt8)((TRANSPARENT_COLOR & 0xFF00)>>8);
    535     M4OSA_UInt8 transparent2 = (M4OSA_UInt8)TRANSPARENT_COLOR;
    536 
    537 #ifndef DECODE_GIF_ON_SAVING
    538     Framing = (M4xVSS_FramingStruct *)userData;
    539     currentFraming = (M4xVSS_FramingStruct *)Framing->pCurrent;
    540     FramingRGB = Framing->FramingRgb->pac_data;
    541 #endif /*DECODE_GIF_ON_SAVING*/
    542 
    543 #ifdef DECODE_GIF_ON_SAVING
    544     M4OSA_ERR err;
    545     Framing =
    546      (M4xVSS_FramingStruct *)((M4xVSS_FramingContext*)userData)->aFramingCtx;
    547     if(Framing == M4OSA_NULL)
    548     {
    549         ((M4xVSS_FramingContext*)userData)->clipTime = pProgress->uiOutputTime;
    550         err = M4xVSS_internalDecodeGIF(userData);
    551         if(M4NO_ERROR != err)
    552         {
    553             M4OSA_TRACE1_1("M4VSS3GPP_externalVideoEffectFraming: \
    554                 Error in M4xVSS_internalDecodeGIF: 0x%x", err);
    555             return err;
    556         }
    557         Framing =
    558          (M4xVSS_FramingStruct *)((M4xVSS_FramingContext*)userData)->aFramingCtx;
    559         /* Initializes first GIF time */
    560         ((M4xVSS_FramingContext*)userData)->current_gif_time =
    561           pProgress->uiOutputTime;
    562     }
    563     currentFraming = (M4xVSS_FramingStruct *)Framing;
    564     FramingRGB = Framing->FramingRgb->pac_data;
    565 #endif /*DECODE_GIF_ON_SAVING*/
    566 
    567     /**
    568      * Initialize input / output plane pointers */
    569     p_in_Y += PlaneIn[0].u_topleft;
    570     p_in_U += PlaneIn[1].u_topleft;
    571     p_in_V += PlaneIn[2].u_topleft;
    572 
    573     p_out0 = PlaneOut[0].pac_data;
    574     p_out1 = PlaneOut[1].pac_data;
    575     p_out2 = PlaneOut[2].pac_data;
    576 
    577     /**
    578      * Depending on time, initialize Framing frame to use */
    579     if(Framing->previousClipTime == -1)
    580     {
    581         Framing->previousClipTime = pProgress->uiOutputTime;
    582     }
    583 
    584     /**
    585      * If the current clip time has reach the duration of one frame of the framing picture
    586      * we need to step to next framing picture */
    587 #ifdef DECODE_GIF_ON_SAVING
    588     if(((M4xVSS_FramingContext*)userData)->b_animated == M4OSA_TRUE)
    589     {
    590         while((((M4xVSS_FramingContext*)userData)->current_gif_time + currentFraming->duration) < pProgress->uiOutputTime)
    591         {
    592             ((M4xVSS_FramingContext*)userData)->clipTime =
    593              pProgress->uiOutputTime;
    594 
    595             err = M4xVSS_internalDecodeGIF(userData);
    596             if(M4NO_ERROR != err)
    597             {
    598                 M4OSA_TRACE1_1("M4VSS3GPP_externalVideoEffectFraming: Error in M4xVSS_internalDecodeGIF: 0x%x", err);
    599                 return err;
    600             }
    601             if(currentFraming->duration != 0)
    602             {
    603                 ((M4xVSS_FramingContext*)userData)->current_gif_time += currentFraming->duration;
    604             }
    605             else
    606             {
    607                 ((M4xVSS_FramingContext*)userData)->current_gif_time +=
    608                  pProgress->uiOutputTime - Framing->previousClipTime;
    609             }
    610             Framing = (M4xVSS_FramingStruct *)((M4xVSS_FramingContext*)userData)->aFramingCtx;
    611             currentFraming = (M4xVSS_FramingStruct *)Framing;
    612             FramingRGB = Framing->FramingRgb->pac_data;
    613         }
    614     }
    615 #else
    616             Framing->pCurrent = currentFraming->pNext;
    617             currentFraming = (M4xVSS_FramingStruct*)Framing->pCurrent;
    618 #endif /*DECODE_GIF_ON_SAVING*/
    619 
    620     Framing->previousClipTime = pProgress->uiOutputTime;
    621     FramingRGB = currentFraming->FramingRgb->pac_data;
    622     topleft[0] = currentFraming->topleft_x;
    623     topleft[1] = currentFraming->topleft_y;
    624 
    625     for( x=0 ;x < PlaneIn[0].u_height ; x++)
    626     {
    627         for( y=0 ;y < PlaneIn[0].u_width ; y++)
    628         {
    629             /**
    630              * To handle framing with input size != output size
    631              * Framing is applyed if coordinates matches between framing/topleft and input plane */
    632             if( y < (topleft[0] + currentFraming->FramingYuv[0].u_width)  &&
    633                 y >= topleft[0] &&
    634                 x < (topleft[1] + currentFraming->FramingYuv[0].u_height) &&
    635                 x >= topleft[1])
    636             {
    637 
    638                 /*Alpha blending support*/
    639                 M4OSA_Float alphaBlending = 1;
    640 #ifdef DECODE_GIF_ON_SAVING
    641                 M4xVSS_internalEffectsAlphaBlending* alphaBlendingStruct =
    642                  (M4xVSS_internalEffectsAlphaBlending*)((M4xVSS_FramingContext*)userData)->alphaBlendingStruct;
    643 #else
    644                 M4xVSS_internalEffectsAlphaBlending* alphaBlendingStruct =
    645                  (M4xVSS_internalEffectsAlphaBlending*)((M4xVSS_FramingStruct*)userData)->alphaBlendingStruct;
    646 #endif //#ifdef DECODE_GIF_ON_SAVING
    647 
    648                 if(alphaBlendingStruct != M4OSA_NULL)
    649                 {
    650                     if(pProgress->uiProgress < (M4OSA_UInt32)(alphaBlendingStruct->m_fadeInTime*10))
    651                     {
    652                         alphaBlending = ((M4OSA_Float)(alphaBlendingStruct->m_middle - alphaBlendingStruct->m_start)*pProgress->uiProgress/(alphaBlendingStruct->m_fadeInTime*10));
    653                         alphaBlending += alphaBlendingStruct->m_start;
    654                         alphaBlending /= 100;
    655                     }
    656                     else if(pProgress->uiProgress >= (M4OSA_UInt32)(alphaBlendingStruct->m_fadeInTime*10) && pProgress->uiProgress < 1000 - (M4OSA_UInt32)(alphaBlendingStruct->m_fadeOutTime*10))
    657                     {
    658                         alphaBlending = (M4OSA_Float)((M4OSA_Float)alphaBlendingStruct->m_middle/100);
    659                     }
    660                     else if(pProgress->uiProgress >= 1000 - (M4OSA_UInt32)(alphaBlendingStruct->m_fadeOutTime*10))
    661                     {
    662                         alphaBlending = ((M4OSA_Float)(alphaBlendingStruct->m_middle - alphaBlendingStruct->m_end))*(1000 - pProgress->uiProgress)/(alphaBlendingStruct->m_fadeOutTime*10);
    663                         alphaBlending += alphaBlendingStruct->m_end;
    664                         alphaBlending /= 100;
    665                     }
    666                 }
    667 
    668                 /**/
    669 
    670                 if((*(FramingRGB)==transparent1) && (*(FramingRGB+1)==transparent2))
    671                 {
    672                     *( p_out0+y+x*PlaneOut[0].u_stride)=(*(p_in_Y+y+x*PlaneIn[0].u_stride));
    673                     *( p_out1+(y>>1)+(x>>1)*PlaneOut[1].u_stride)=(*(p_in_U+(y>>1)+(x>>1)*PlaneIn[1].u_stride));
    674                     *( p_out2+(y>>1)+(x>>1)*PlaneOut[2].u_stride)=(*(p_in_V+(y>>1)+(x>>1)*PlaneIn[2].u_stride));
    675                 }
    676                 else
    677                 {
    678                     *( p_out0+y+x*PlaneOut[0].u_stride)=(*(currentFraming->FramingYuv[0].pac_data+(y-topleft[0])+(x-topleft[1])*currentFraming->FramingYuv[0].u_stride))*alphaBlending;
    679                     *( p_out0+y+x*PlaneOut[0].u_stride)+=(*(p_in_Y+y+x*PlaneIn[0].u_stride))*(1-alphaBlending);
    680                     *( p_out1+(y>>1)+(x>>1)*PlaneOut[1].u_stride)=(*(currentFraming->FramingYuv[1].pac_data+((y-topleft[0])>>1)+((x-topleft[1])>>1)*currentFraming->FramingYuv[1].u_stride))*alphaBlending;
    681                     *( p_out1+(y>>1)+(x>>1)*PlaneOut[1].u_stride)+=(*(p_in_U+(y>>1)+(x>>1)*PlaneIn[1].u_stride))*(1-alphaBlending);
    682                     *( p_out2+(y>>1)+(x>>1)*PlaneOut[2].u_stride)=(*(currentFraming->FramingYuv[2].pac_data+((y-topleft[0])>>1)+((x-topleft[1])>>1)*currentFraming->FramingYuv[2].u_stride))*alphaBlending;
    683                     *( p_out2+(y>>1)+(x>>1)*PlaneOut[2].u_stride)+=(*(p_in_V+(y>>1)+(x>>1)*PlaneIn[2].u_stride))*(1-alphaBlending);
    684                 }
    685                 if( PlaneIn[0].u_width < (topleft[0] + currentFraming->FramingYuv[0].u_width) &&
    686                     y == PlaneIn[0].u_width-1)
    687                 {
    688                     FramingRGB = FramingRGB + 2 * (topleft[0] + currentFraming->FramingYuv[0].u_width - PlaneIn[0].u_width + 1);
    689                 }
    690                 else
    691                 {
    692                     FramingRGB = FramingRGB + 2;
    693                 }
    694             }
    695             /**
    696              * Just copy input plane to output plane */
    697             else
    698             {
    699                 *( p_out0+y+x*PlaneOut[0].u_stride)=*(p_in_Y+y+x*PlaneIn[0].u_stride);
    700                 *( p_out1+(y>>1)+(x>>1)*PlaneOut[1].u_stride)=*(p_in_U+(y>>1)+(x>>1)*PlaneIn[1].u_stride);
    701                 *( p_out2+(y>>1)+(x>>1)*PlaneOut[2].u_stride)=*(p_in_V+(y>>1)+(x>>1)*PlaneIn[2].u_stride);
    702             }
    703         }
    704     }
    705 
    706 #ifdef DECODE_GIF_ON_SAVING
    707     if(pProgress->bIsLast == M4OSA_TRUE
    708         && (M4OSA_Bool)((M4xVSS_FramingContext*)userData)->b_IsFileGif == M4OSA_TRUE)
    709     {
    710         M4xVSS_internalDecodeGIF_Cleaning((M4xVSS_FramingContext*)userData);
    711     }
    712 #endif /*DECODE_GIF_ON_SAVING*/
    713     return M4VIFI_OK;
    714 }
    715 
    716 
    717 /**
    718  ******************************************************************************
    719  * prototype    M4VSS3GPP_externalVideoEffectFifties(M4OSA_Void *pFunctionContext,
    720  *                                                  M4VIFI_ImagePlane *PlaneIn,
    721  *                                                  M4VIFI_ImagePlane *PlaneOut,
    722  *                                                  M4VSS3GPP_ExternalProgress *pProgress,
    723  *                                                  M4OSA_UInt32 uiEffectKind)
    724  *
    725  * @brief   This function make a video look as if it was taken in the fifties
    726  * @note
    727  * @param   pUserData       (IN) Context
    728  * @param   pPlaneIn        (IN) Input YUV420 planar
    729  * @param   pPlaneOut       (IN/OUT) Output YUV420 planar
    730  * @param   pProgress       (IN/OUT) Progress indication (0-100)
    731  * @param   uiEffectKind    (IN) Unused
    732  *
    733  * @return  M4VIFI_OK:          No error
    734  * @return  M4ERR_PARAMETER:    pFiftiesData, pPlaneOut or pProgress are NULL (DEBUG only)
    735  ******************************************************************************
    736 */
    737 M4OSA_ERR M4VSS3GPP_externalVideoEffectFifties(
    738     M4OSA_Void *pUserData, M4VIFI_ImagePlane *pPlaneIn,
    739     M4VIFI_ImagePlane *pPlaneOut, M4VSS3GPP_ExternalProgress *pProgress,
    740     M4OSA_UInt32 uiEffectKind )
    741 {
    742     M4VIFI_UInt32 x, y, xShift;
    743     M4VIFI_UInt8 *pInY = pPlaneIn[0].pac_data;
    744     M4VIFI_UInt8 *pOutY, *pInYbegin;
    745     M4VIFI_UInt8 *pInCr,* pOutCr;
    746     M4VIFI_Int32 plane_number;
    747 
    748     /* Internal context*/
    749     M4xVSS_FiftiesStruct* p_FiftiesData = (M4xVSS_FiftiesStruct *)pUserData;
    750 
    751     /* Initialize input / output plane pointers */
    752     pInY += pPlaneIn[0].u_topleft;
    753     pOutY = pPlaneOut[0].pac_data;
    754     pInYbegin  = pInY;
    755 
    756     /* Initialize the random */
    757     if(p_FiftiesData->previousClipTime < 0)
    758     {
    759         M4OSA_randInit();
    760         M4OSA_rand((M4OSA_Int32*)&(p_FiftiesData->shiftRandomValue), (pPlaneIn[0].u_height) >> 4);
    761         M4OSA_rand((M4OSA_Int32*)&(p_FiftiesData->stripeRandomValue), (pPlaneIn[0].u_width)<< 2);
    762         p_FiftiesData->previousClipTime = pProgress->uiOutputTime;
    763     }
    764 
    765     /* Choose random values if we have reached the duration of a partial effect */
    766     else if( (pProgress->uiOutputTime - p_FiftiesData->previousClipTime) > p_FiftiesData->fiftiesEffectDuration)
    767     {
    768         M4OSA_rand((M4OSA_Int32*)&(p_FiftiesData->shiftRandomValue), (pPlaneIn[0].u_height) >> 4);
    769         M4OSA_rand((M4OSA_Int32*)&(p_FiftiesData->stripeRandomValue), (pPlaneIn[0].u_width)<< 2);
    770         p_FiftiesData->previousClipTime = pProgress->uiOutputTime;
    771     }
    772 
    773     /* Put in Sepia the chrominance */
    774     for (plane_number = 1; plane_number < 3; plane_number++)
    775     {
    776         pInCr  = pPlaneIn[plane_number].pac_data  + pPlaneIn[plane_number].u_topleft;
    777         pOutCr = pPlaneOut[plane_number].pac_data + pPlaneOut[plane_number].u_topleft;
    778 
    779         for (x = 0; x < pPlaneOut[plane_number].u_height; x++)
    780         {
    781             if (1 == plane_number)
    782                 memset((void *)pOutCr, 117,pPlaneIn[plane_number].u_width); /* U value */
    783             else
    784                 memset((void *)pOutCr, 139,pPlaneIn[plane_number].u_width); /* V value */
    785 
    786             pInCr  += pPlaneIn[plane_number].u_stride;
    787             pOutCr += pPlaneOut[plane_number].u_stride;
    788         }
    789     }
    790 
    791     /* Compute the new pixels values */
    792     for( x = 0 ; x < pPlaneIn[0].u_height ; x++)
    793     {
    794         M4VIFI_UInt8 *p_outYtmp, *p_inYtmp;
    795 
    796         /* Compute the xShift (random value) */
    797         if (0 == (p_FiftiesData->shiftRandomValue % 5 ))
    798             xShift = (x + p_FiftiesData->shiftRandomValue ) % (pPlaneIn[0].u_height - 1);
    799         else
    800             xShift = (x + (pPlaneIn[0].u_height - p_FiftiesData->shiftRandomValue) ) % (pPlaneIn[0].u_height - 1);
    801 
    802         /* Initialize the pointers */
    803         p_outYtmp = pOutY + 1;                                    /* yShift of 1 pixel */
    804         p_inYtmp  = pInYbegin + (xShift * pPlaneIn[0].u_stride);  /* Apply the xShift */
    805 
    806         for( y = 0 ; y < pPlaneIn[0].u_width ; y++)
    807         {
    808             /* Set Y value */
    809             if (xShift > (pPlaneIn[0].u_height - 4))
    810                 *p_outYtmp = 40;        /* Add some horizontal black lines between the two parts of the image */
    811             else if ( y == p_FiftiesData->stripeRandomValue)
    812                 *p_outYtmp = 90;        /* Add a random vertical line for the bulk */
    813             else
    814                 *p_outYtmp = *p_inYtmp;
    815 
    816 
    817             /* Go to the next pixel */
    818             p_outYtmp++;
    819             p_inYtmp++;
    820 
    821             /* Restart at the beginning of the line for the last pixel*/
    822             if (y == (pPlaneIn[0].u_width - 2))
    823                 p_outYtmp = pOutY;
    824         }
    825 
    826         /* Go to the next line */
    827         pOutY += pPlaneOut[0].u_stride;
    828     }
    829 
    830     return M4VIFI_OK;
    831 }
    832 
    833 unsigned char M4VFL_modifyLumaWithScale(M4ViComImagePlane *plane_in,
    834                                         M4ViComImagePlane *plane_out,
    835                                         unsigned long lum_factor,
    836                                         void *user_data)
    837 {
    838     unsigned short *p_src, *p_dest, *p_src_line, *p_dest_line;
    839     unsigned char *p_csrc, *p_cdest, *p_csrc_line, *p_cdest_line;
    840     unsigned long pix_src;
    841     unsigned long u_outpx, u_outpx2;
    842     unsigned long u_width, u_stride, u_stride_out,u_height, pix;
    843     long i, j;
    844 
    845     /* copy or filter chroma */
    846     u_width = plane_in[1].u_width;
    847     u_height = plane_in[1].u_height;
    848     u_stride = plane_in[1].u_stride;
    849     u_stride_out = plane_out[1].u_stride;
    850     p_cdest_line = (unsigned char *) &plane_out[1].pac_data[plane_out[1].u_topleft];
    851     p_csrc_line = (unsigned char *) &plane_in[1].pac_data[plane_in[1].u_topleft];
    852 
    853     if (lum_factor > 256)
    854     {
    855         p_cdest = (unsigned char *) &plane_out[2].pac_data[plane_out[2].u_topleft];
    856         p_csrc = (unsigned char *) &plane_in[2].pac_data[plane_in[2].u_topleft];
    857         /* copy chroma */
    858         for (j = u_height; j != 0; j--)
    859         {
    860             for (i = u_width; i != 0; i--)
    861             {
    862                 memcpy((void *)p_cdest_line, (void *)p_csrc_line, u_width);
    863                 memcpy((void *)p_cdest, (void *)p_csrc, u_width);
    864             }
    865             p_cdest_line += u_stride_out;
    866             p_cdest += u_stride_out;
    867             p_csrc_line += u_stride;
    868             p_csrc += u_stride;
    869         }
    870     }
    871     else
    872     {
    873         /* filter chroma */
    874         pix = (1024 - lum_factor) << 7;
    875         for (j = u_height; j != 0; j--)
    876         {
    877             p_cdest = p_cdest_line;
    878             p_csrc = p_csrc_line;
    879             for (i = u_width; i != 0; i--)
    880             {
    881                 *p_cdest++ = ((pix + (*p_csrc++ & 0xFF) * lum_factor) >> LUM_FACTOR_MAX);
    882             }
    883             p_cdest_line += u_stride_out;
    884             p_csrc_line += u_stride;
    885         }
    886         p_cdest_line = (unsigned char *) &plane_out[2].pac_data[plane_out[2].u_topleft];
    887         p_csrc_line = (unsigned char *) &plane_in[2].pac_data[plane_in[2].u_topleft];
    888         for (j = u_height; j != 0; j--)
    889         {
    890             p_cdest = p_cdest_line;
    891             p_csrc = p_csrc_line;
    892             for (i = u_width; i != 0; i--)
    893             {
    894                 *p_cdest++ = ((pix + (*p_csrc & 0xFF) * lum_factor) >> LUM_FACTOR_MAX);
    895             }
    896             p_cdest_line += u_stride_out;
    897             p_csrc_line += u_stride;
    898         }
    899     }
    900     /* apply luma factor */
    901     u_width = plane_in[0].u_width;
    902     u_height = plane_in[0].u_height;
    903     u_stride = (plane_in[0].u_stride >> 1);
    904     u_stride_out = (plane_out[0].u_stride >> 1);
    905     p_dest = (unsigned short *) &plane_out[0].pac_data[plane_out[0].u_topleft];
    906     p_src = (unsigned short *) &plane_in[0].pac_data[plane_in[0].u_topleft];
    907     p_dest_line = p_dest;
    908     p_src_line = p_src;
    909 
    910     for (j = u_height; j != 0; j--)
    911     {
    912         p_dest = p_dest_line;
    913         p_src = p_src_line;
    914         for (i = (u_width >> 1); i != 0; i--)
    915         {
    916             pix_src = (unsigned long) *p_src++;
    917             pix = pix_src & 0xFF;
    918             u_outpx = ((pix * lum_factor) >> LUM_FACTOR_MAX);
    919             pix = ((pix_src & 0xFF00) >> 8);
    920             u_outpx2 = (((pix * lum_factor) >> LUM_FACTOR_MAX)<< 8) ;
    921             *p_dest++ = (unsigned short) (u_outpx2 | u_outpx);
    922         }
    923         p_dest_line += u_stride_out;
    924         p_src_line += u_stride;
    925     }
    926 
    927     return 0;
    928 }
    929 
    930 /******************************************************************************
    931  * prototype    M4OSA_ERR M4xVSS_internalConvertRGBtoYUV(M4xVSS_FramingStruct* framingCtx)
    932  * @brief   This function converts an RGB565 plane to YUV420 planar
    933  * @note    It is used only for framing effect
    934  *          It allocates output YUV planes
    935  * @param   framingCtx  (IN) The framing struct containing input RGB565 plane
    936  *
    937  * @return  M4NO_ERROR: No error
    938  * @return  M4ERR_PARAMETER: At least one of the function parameters is null
    939  * @return  M4ERR_ALLOC: Allocation error (no more memory)
    940  ******************************************************************************
    941 */
    942 M4OSA_ERR M4xVSS_internalConvertRGBtoYUV(M4xVSS_FramingStruct* framingCtx)
    943 {
    944     M4OSA_ERR err;
    945 
    946     /**
    947      * Allocate output YUV planes */
    948     framingCtx->FramingYuv = (M4VIFI_ImagePlane*)M4OSA_32bitAlignedMalloc(3*sizeof(M4VIFI_ImagePlane), M4VS, (M4OSA_Char*)"M4xVSS_internalConvertRGBtoYUV: Output plane YUV");
    949     if(framingCtx->FramingYuv == M4OSA_NULL)
    950     {
    951         M4OSA_TRACE1_0("Allocation error in M4xVSS_internalConvertRGBtoYUV");
    952         return M4ERR_ALLOC;
    953     }
    954     framingCtx->FramingYuv[0].u_width = framingCtx->FramingRgb->u_width;
    955     framingCtx->FramingYuv[0].u_height = framingCtx->FramingRgb->u_height;
    956     framingCtx->FramingYuv[0].u_topleft = 0;
    957     framingCtx->FramingYuv[0].u_stride = framingCtx->FramingRgb->u_width;
    958     framingCtx->FramingYuv[0].pac_data = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc((framingCtx->FramingYuv[0].u_width*framingCtx->FramingYuv[0].u_height*3)>>1, M4VS, (M4OSA_Char*)"Alloc for the Convertion output YUV");;
    959     if(framingCtx->FramingYuv[0].pac_data == M4OSA_NULL)
    960     {
    961         M4OSA_TRACE1_0("Allocation error in M4xVSS_internalConvertRGBtoYUV");
    962         return M4ERR_ALLOC;
    963     }
    964     framingCtx->FramingYuv[1].u_width = (framingCtx->FramingRgb->u_width)>>1;
    965     framingCtx->FramingYuv[1].u_height = (framingCtx->FramingRgb->u_height)>>1;
    966     framingCtx->FramingYuv[1].u_topleft = 0;
    967     framingCtx->FramingYuv[1].u_stride = (framingCtx->FramingRgb->u_width)>>1;
    968     framingCtx->FramingYuv[1].pac_data = framingCtx->FramingYuv[0].pac_data + framingCtx->FramingYuv[0].u_width * framingCtx->FramingYuv[0].u_height;
    969     framingCtx->FramingYuv[2].u_width = (framingCtx->FramingRgb->u_width)>>1;
    970     framingCtx->FramingYuv[2].u_height = (framingCtx->FramingRgb->u_height)>>1;
    971     framingCtx->FramingYuv[2].u_topleft = 0;
    972     framingCtx->FramingYuv[2].u_stride = (framingCtx->FramingRgb->u_width)>>1;
    973     framingCtx->FramingYuv[2].pac_data = framingCtx->FramingYuv[1].pac_data + framingCtx->FramingYuv[1].u_width * framingCtx->FramingYuv[1].u_height;
    974 
    975     /**
    976      * Convert input RGB 565 to YUV 420 to be able to merge it with output video in framing effect */
    977     err = M4VIFI_xVSS_RGB565toYUV420(M4OSA_NULL, framingCtx->FramingRgb, framingCtx->FramingYuv);
    978     if(err != M4NO_ERROR)
    979     {
    980         M4OSA_TRACE1_1("M4xVSS_internalConvertRGBtoYUV: error when converting from RGB to YUV: 0x%x\n", err);
    981     }
    982 
    983     framingCtx->duration = 0;
    984     framingCtx->previousClipTime = -1;
    985     framingCtx->previewOffsetClipTime = -1;
    986 
    987     /**
    988      * Only one element in the chained list (no animated image with RGB buffer...) */
    989     framingCtx->pCurrent = framingCtx;
    990     framingCtx->pNext = framingCtx;
    991 
    992     return M4NO_ERROR;
    993 }
    994 
    995 /******************************************************************************
    996  * prototype    M4OSA_ERR M4xVSS_internalConvertRGB888toYUV(M4xVSS_FramingStruct* framingCtx)
    997  * @brief   This function converts an RGB888 plane to YUV420 planar
    998  * @note    It is used only for framing effect
    999  *          It allocates output YUV planes
   1000  * @param   framingCtx  (IN) The framing struct containing input RGB888 plane
   1001  *
   1002  * @return  M4NO_ERROR: No error
   1003  * @return  M4ERR_PARAMETER: At least one of the function parameters is null
   1004  * @return  M4ERR_ALLOC: Allocation error (no more memory)
   1005  ******************************************************************************
   1006 */
   1007 M4OSA_ERR M4xVSS_internalConvertRGB888toYUV(M4xVSS_FramingStruct* framingCtx)
   1008 {
   1009     M4OSA_ERR err;
   1010 
   1011     /**
   1012      * Allocate output YUV planes */
   1013     framingCtx->FramingYuv = (M4VIFI_ImagePlane*)M4OSA_32bitAlignedMalloc(3*sizeof(M4VIFI_ImagePlane), M4VS, (M4OSA_Char*)"M4xVSS_internalConvertRGBtoYUV: Output plane YUV");
   1014     if(framingCtx->FramingYuv == M4OSA_NULL)
   1015     {
   1016         M4OSA_TRACE1_0("Allocation error in M4xVSS_internalConvertRGBtoYUV");
   1017         return M4ERR_ALLOC;
   1018     }
   1019     framingCtx->FramingYuv[0].u_width = framingCtx->FramingRgb->u_width;
   1020     framingCtx->FramingYuv[0].u_height = framingCtx->FramingRgb->u_height;
   1021     framingCtx->FramingYuv[0].u_topleft = 0;
   1022     framingCtx->FramingYuv[0].u_stride = framingCtx->FramingRgb->u_width;
   1023     framingCtx->FramingYuv[0].pac_data = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc((framingCtx->FramingYuv[0].u_width*framingCtx->FramingYuv[0].u_height*3)>>1, M4VS, (M4OSA_Char*)"Alloc for the Convertion output YUV");;
   1024     if(framingCtx->FramingYuv[0].pac_data == M4OSA_NULL)
   1025     {
   1026         M4OSA_TRACE1_0("Allocation error in M4xVSS_internalConvertRGBtoYUV");
   1027         return M4ERR_ALLOC;
   1028     }
   1029     framingCtx->FramingYuv[1].u_width = (framingCtx->FramingRgb->u_width)>>1;
   1030     framingCtx->FramingYuv[1].u_height = (framingCtx->FramingRgb->u_height)>>1;
   1031     framingCtx->FramingYuv[1].u_topleft = 0;
   1032     framingCtx->FramingYuv[1].u_stride = (framingCtx->FramingRgb->u_width)>>1;
   1033     framingCtx->FramingYuv[1].pac_data = framingCtx->FramingYuv[0].pac_data + framingCtx->FramingYuv[0].u_width * framingCtx->FramingYuv[0].u_height;
   1034     framingCtx->FramingYuv[2].u_width = (framingCtx->FramingRgb->u_width)>>1;
   1035     framingCtx->FramingYuv[2].u_height = (framingCtx->FramingRgb->u_height)>>1;
   1036     framingCtx->FramingYuv[2].u_topleft = 0;
   1037     framingCtx->FramingYuv[2].u_stride = (framingCtx->FramingRgb->u_width)>>1;
   1038     framingCtx->FramingYuv[2].pac_data = framingCtx->FramingYuv[1].pac_data + framingCtx->FramingYuv[1].u_width * framingCtx->FramingYuv[1].u_height;
   1039 
   1040     /**
   1041      * Convert input RGB888 to YUV 420 to be able to merge it with output video in framing effect */
   1042     err = M4VIFI_RGB888toYUV420(M4OSA_NULL, framingCtx->FramingRgb, framingCtx->FramingYuv);
   1043     if(err != M4NO_ERROR)
   1044     {
   1045         M4OSA_TRACE1_1("M4xVSS_internalConvertRGBtoYUV: error when converting from RGB to YUV: 0x%x\n", err);
   1046     }
   1047 
   1048     framingCtx->duration = 0;
   1049     framingCtx->previousClipTime = -1;
   1050     framingCtx->previewOffsetClipTime = -1;
   1051 
   1052     /**
   1053      * Only one element in the chained list (no animated image with RGB buffer...) */
   1054     framingCtx->pCurrent = framingCtx;
   1055     framingCtx->pNext = framingCtx;
   1056 
   1057     return M4NO_ERROR;
   1058 }
   1059 
   1060 /**
   1061  ******************************************************************************
   1062  * M4VIFI_UInt8 M4VIFI_RGB565toYUV420 (void *pUserData,
   1063  *                                   M4VIFI_ImagePlane *pPlaneIn,
   1064  *                                   M4VIFI_ImagePlane *pPlaneOut)
   1065  * @author  Patrice Martinez / Philips Digital Networks - MP4Net
   1066  * @brief   transform RGB565 image to a YUV420 image.
   1067  * @note    Convert RGB565 to YUV420,
   1068  *          Loop on each row ( 2 rows by 2 rows )
   1069  *              Loop on each column ( 2 col by 2 col )
   1070  *                  Get 4 RGB samples from input data and build 4 output Y samples
   1071  *                  and each single U & V data
   1072  *              end loop on col
   1073  *          end loop on row
   1074  * @param   pUserData: (IN) User Specific Data
   1075  * @param   pPlaneIn: (IN) Pointer to RGB565 Plane
   1076  * @param   pPlaneOut: (OUT) Pointer to  YUV420 buffer Plane
   1077  * @return  M4VIFI_OK: there is no error
   1078  * @return  M4VIFI_ILLEGAL_FRAME_HEIGHT: YUV Plane height is ODD
   1079  * @return  M4VIFI_ILLEGAL_FRAME_WIDTH:  YUV Plane width is ODD
   1080  ******************************************************************************
   1081 */
   1082 M4VIFI_UInt8    M4VIFI_xVSS_RGB565toYUV420(void *pUserData, M4VIFI_ImagePlane *pPlaneIn,
   1083                                                       M4VIFI_ImagePlane *pPlaneOut)
   1084 {
   1085     M4VIFI_UInt32   u32_width, u32_height;
   1086     M4VIFI_UInt32   u32_stride_Y, u32_stride2_Y, u32_stride_U, u32_stride_V;
   1087     M4VIFI_UInt32   u32_stride_rgb, u32_stride_2rgb;
   1088     M4VIFI_UInt32   u32_col, u32_row;
   1089 
   1090     M4VIFI_Int32    i32_r00, i32_r01, i32_r10, i32_r11;
   1091     M4VIFI_Int32    i32_g00, i32_g01, i32_g10, i32_g11;
   1092     M4VIFI_Int32    i32_b00, i32_b01, i32_b10, i32_b11;
   1093     M4VIFI_Int32    i32_y00, i32_y01, i32_y10, i32_y11;
   1094     M4VIFI_Int32    i32_u00, i32_u01, i32_u10, i32_u11;
   1095     M4VIFI_Int32    i32_v00, i32_v01, i32_v10, i32_v11;
   1096     M4VIFI_UInt8    *pu8_yn, *pu8_ys, *pu8_u, *pu8_v;
   1097     M4VIFI_UInt8    *pu8_y_data, *pu8_u_data, *pu8_v_data;
   1098     M4VIFI_UInt8    *pu8_rgbn_data, *pu8_rgbn;
   1099     M4VIFI_UInt16   u16_pix1, u16_pix2, u16_pix3, u16_pix4;
   1100     M4VIFI_UInt8 count_null=0;
   1101 
   1102     /* Check planes height are appropriate */
   1103     if( (pPlaneIn->u_height != pPlaneOut[0].u_height)           ||
   1104         (pPlaneOut[0].u_height != (pPlaneOut[1].u_height<<1))   ||
   1105         (pPlaneOut[0].u_height != (pPlaneOut[2].u_height<<1)))
   1106     {
   1107         return M4VIFI_ILLEGAL_FRAME_HEIGHT;
   1108     }
   1109 
   1110     /* Check planes width are appropriate */
   1111     if( (pPlaneIn->u_width != pPlaneOut[0].u_width)         ||
   1112         (pPlaneOut[0].u_width != (pPlaneOut[1].u_width<<1)) ||
   1113         (pPlaneOut[0].u_width != (pPlaneOut[2].u_width<<1)))
   1114     {
   1115         return M4VIFI_ILLEGAL_FRAME_WIDTH;
   1116     }
   1117 
   1118     /* Set the pointer to the beginning of the output data buffers */
   1119     pu8_y_data = pPlaneOut[0].pac_data + pPlaneOut[0].u_topleft;
   1120     pu8_u_data = pPlaneOut[1].pac_data + pPlaneOut[1].u_topleft;
   1121     pu8_v_data = pPlaneOut[2].pac_data + pPlaneOut[2].u_topleft;
   1122 
   1123     /* Set the pointer to the beginning of the input data buffers */
   1124     pu8_rgbn_data   = pPlaneIn->pac_data + pPlaneIn->u_topleft;
   1125 
   1126     /* Get the size of the output image */
   1127     u32_width = pPlaneOut[0].u_width;
   1128     u32_height = pPlaneOut[0].u_height;
   1129 
   1130     /* Set the size of the memory jumps corresponding to row jump in each output plane */
   1131     u32_stride_Y = pPlaneOut[0].u_stride;
   1132     u32_stride2_Y = u32_stride_Y << 1;
   1133     u32_stride_U = pPlaneOut[1].u_stride;
   1134     u32_stride_V = pPlaneOut[2].u_stride;
   1135 
   1136     /* Set the size of the memory jumps corresponding to row jump in input plane */
   1137     u32_stride_rgb = pPlaneIn->u_stride;
   1138     u32_stride_2rgb = u32_stride_rgb << 1;
   1139 
   1140 
   1141     /* Loop on each row of the output image, input coordinates are estimated from output ones */
   1142     /* Two YUV rows are computed at each pass */
   1143     for (u32_row = u32_height ;u32_row != 0; u32_row -=2)
   1144     {
   1145         /* Current Y plane row pointers */
   1146         pu8_yn = pu8_y_data;
   1147         /* Next Y plane row pointers */
   1148         pu8_ys = pu8_yn + u32_stride_Y;
   1149         /* Current U plane row pointer */
   1150         pu8_u = pu8_u_data;
   1151         /* Current V plane row pointer */
   1152         pu8_v = pu8_v_data;
   1153 
   1154         pu8_rgbn = pu8_rgbn_data;
   1155 
   1156         /* Loop on each column of the output image */
   1157         for (u32_col = u32_width; u32_col != 0 ; u32_col -=2)
   1158         {
   1159             /* Get four RGB 565 samples from input data */
   1160             u16_pix1 = *( (M4VIFI_UInt16 *) pu8_rgbn);
   1161             u16_pix2 = *( (M4VIFI_UInt16 *) (pu8_rgbn + CST_RGB_16_SIZE));
   1162             u16_pix3 = *( (M4VIFI_UInt16 *) (pu8_rgbn + u32_stride_rgb));
   1163             u16_pix4 = *( (M4VIFI_UInt16 *) (pu8_rgbn + u32_stride_rgb + CST_RGB_16_SIZE));
   1164 
   1165             /* Unpack RGB565 to 8bit R, G, B */
   1166             /* (x,y) */
   1167             GET_RGB565(i32_b00,i32_g00,i32_r00,u16_pix1);
   1168             /* (x+1,y) */
   1169             GET_RGB565(i32_b10,i32_g10,i32_r10,u16_pix2);
   1170             /* (x,y+1) */
   1171             GET_RGB565(i32_b01,i32_g01,i32_r01,u16_pix3);
   1172             /* (x+1,y+1) */
   1173             GET_RGB565(i32_b11,i32_g11,i32_r11,u16_pix4);
   1174             /* If RGB is transparent color (0, 63, 0), we transform it to white (31,63,31) */
   1175             if(i32_b00 == 0 && i32_g00 == 63 && i32_r00 == 0)
   1176             {
   1177                 i32_b00 = 31;
   1178                 i32_r00 = 31;
   1179             }
   1180             if(i32_b10 == 0 && i32_g10 == 63 && i32_r10 == 0)
   1181             {
   1182                 i32_b10 = 31;
   1183                 i32_r10 = 31;
   1184             }
   1185             if(i32_b01 == 0 && i32_g01 == 63 && i32_r01 == 0)
   1186             {
   1187                 i32_b01 = 31;
   1188                 i32_r01 = 31;
   1189             }
   1190             if(i32_b11 == 0 && i32_g11 == 63 && i32_r11 == 0)
   1191             {
   1192                 i32_b11 = 31;
   1193                 i32_r11 = 31;
   1194             }
   1195             /* Convert RGB value to YUV */
   1196             i32_u00 = U16(i32_r00, i32_g00, i32_b00);
   1197             i32_v00 = V16(i32_r00, i32_g00, i32_b00);
   1198             /* luminance value */
   1199             i32_y00 = Y16(i32_r00, i32_g00, i32_b00);
   1200 
   1201             i32_u10 = U16(i32_r10, i32_g10, i32_b10);
   1202             i32_v10 = V16(i32_r10, i32_g10, i32_b10);
   1203             /* luminance value */
   1204             i32_y10 = Y16(i32_r10, i32_g10, i32_b10);
   1205 
   1206             i32_u01 = U16(i32_r01, i32_g01, i32_b01);
   1207             i32_v01 = V16(i32_r01, i32_g01, i32_b01);
   1208             /* luminance value */
   1209             i32_y01 = Y16(i32_r01, i32_g01, i32_b01);
   1210 
   1211             i32_u11 = U16(i32_r11, i32_g11, i32_b11);
   1212             i32_v11 = V16(i32_r11, i32_g11, i32_b11);
   1213             /* luminance value */
   1214             i32_y11 = Y16(i32_r11, i32_g11, i32_b11);
   1215 
   1216             /* Store luminance data */
   1217             pu8_yn[0] = (M4VIFI_UInt8)i32_y00;
   1218             pu8_yn[1] = (M4VIFI_UInt8)i32_y10;
   1219             pu8_ys[0] = (M4VIFI_UInt8)i32_y01;
   1220             pu8_ys[1] = (M4VIFI_UInt8)i32_y11;
   1221             *pu8_u = (M4VIFI_UInt8)((i32_u00 + i32_u01 + i32_u10 + i32_u11 + 2) >> 2);
   1222             *pu8_v = (M4VIFI_UInt8)((i32_v00 + i32_v01 + i32_v10 + i32_v11 + 2) >> 2);
   1223             /* Prepare for next column */
   1224             pu8_rgbn += (CST_RGB_16_SIZE<<1);
   1225             /* Update current Y plane line pointer*/
   1226             pu8_yn += 2;
   1227             /* Update next Y plane line pointer*/
   1228             pu8_ys += 2;
   1229             /* Update U plane line pointer*/
   1230             pu8_u ++;
   1231             /* Update V plane line pointer*/
   1232             pu8_v ++;
   1233         } /* End of horizontal scanning */
   1234 
   1235         /* Prepare pointers for the next row */
   1236         pu8_y_data += u32_stride2_Y;
   1237         pu8_u_data += u32_stride_U;
   1238         pu8_v_data += u32_stride_V;
   1239         pu8_rgbn_data += u32_stride_2rgb;
   1240 
   1241 
   1242     } /* End of vertical scanning */
   1243 
   1244     return M4VIFI_OK;
   1245 }
   1246 
   1247 /***************************************************************************
   1248 Proto:
   1249 M4VIFI_UInt8    M4VIFI_RGB888toYUV420(void *pUserData, M4VIFI_ImagePlane *PlaneIn, M4VIFI_ImagePlane PlaneOut[3]);
   1250 Author:     Patrice Martinez / Philips Digital Networks - MP4Net
   1251 Purpose:    filling of the YUV420 plane from a BGR24 plane
   1252 Abstract:   Loop on each row ( 2 rows by 2 rows )
   1253                 Loop on each column ( 2 col by 2 col )
   1254                     Get 4 BGR samples from input data and build 4 output Y samples and each single U & V data
   1255                 end loop on col
   1256             end loop on row
   1257 
   1258 In:         RGB24 plane
   1259 InOut:      none
   1260 Out:        array of 3 M4VIFI_ImagePlane structures
   1261 Modified:   ML: RGB function modified to BGR.
   1262 ***************************************************************************/
   1263 M4VIFI_UInt8 M4VIFI_RGB888toYUV420(void *pUserData, M4VIFI_ImagePlane *PlaneIn, M4VIFI_ImagePlane PlaneOut[3])
   1264 {
   1265 
   1266     M4VIFI_UInt32   u32_width, u32_height;
   1267     M4VIFI_UInt32   u32_stride_Y, u32_stride2_Y, u32_stride_U, u32_stride_V, u32_stride_rgb, u32_stride_2rgb;
   1268     M4VIFI_UInt32   u32_col, u32_row;
   1269 
   1270     M4VIFI_Int32    i32_r00, i32_r01, i32_r10, i32_r11;
   1271     M4VIFI_Int32    i32_g00, i32_g01, i32_g10, i32_g11;
   1272     M4VIFI_Int32    i32_b00, i32_b01, i32_b10, i32_b11;
   1273     M4VIFI_Int32    i32_y00, i32_y01, i32_y10, i32_y11;
   1274     M4VIFI_Int32    i32_u00, i32_u01, i32_u10, i32_u11;
   1275     M4VIFI_Int32    i32_v00, i32_v01, i32_v10, i32_v11;
   1276     M4VIFI_UInt8    *pu8_yn, *pu8_ys, *pu8_u, *pu8_v;
   1277     M4VIFI_UInt8    *pu8_y_data, *pu8_u_data, *pu8_v_data;
   1278     M4VIFI_UInt8    *pu8_rgbn_data, *pu8_rgbn;
   1279 
   1280     /* check sizes */
   1281     if( (PlaneIn->u_height != PlaneOut[0].u_height)         ||
   1282         (PlaneOut[0].u_height != (PlaneOut[1].u_height<<1)) ||
   1283         (PlaneOut[0].u_height != (PlaneOut[2].u_height<<1)))
   1284         return M4VIFI_ILLEGAL_FRAME_HEIGHT;
   1285 
   1286     if( (PlaneIn->u_width != PlaneOut[0].u_width)       ||
   1287         (PlaneOut[0].u_width != (PlaneOut[1].u_width<<1))   ||
   1288         (PlaneOut[0].u_width != (PlaneOut[2].u_width<<1)))
   1289         return M4VIFI_ILLEGAL_FRAME_WIDTH;
   1290 
   1291 
   1292     /* set the pointer to the beginning of the output data buffers */
   1293     pu8_y_data  = PlaneOut[0].pac_data + PlaneOut[0].u_topleft;
   1294     pu8_u_data  = PlaneOut[1].pac_data + PlaneOut[1].u_topleft;
   1295     pu8_v_data  = PlaneOut[2].pac_data + PlaneOut[2].u_topleft;
   1296 
   1297     /* idem for input buffer */
   1298     pu8_rgbn_data   = PlaneIn->pac_data + PlaneIn->u_topleft;
   1299 
   1300     /* get the size of the output image */
   1301     u32_width   = PlaneOut[0].u_width;
   1302     u32_height  = PlaneOut[0].u_height;
   1303 
   1304     /* set the size of the memory jumps corresponding to row jump in each output plane */
   1305     u32_stride_Y = PlaneOut[0].u_stride;
   1306     u32_stride2_Y= u32_stride_Y << 1;
   1307     u32_stride_U = PlaneOut[1].u_stride;
   1308     u32_stride_V = PlaneOut[2].u_stride;
   1309 
   1310     /* idem for input plane */
   1311     u32_stride_rgb = PlaneIn->u_stride;
   1312     u32_stride_2rgb = u32_stride_rgb << 1;
   1313 
   1314     /* loop on each row of the output image, input coordinates are estimated from output ones */
   1315     /* two YUV rows are computed at each pass */
   1316     for (u32_row = u32_height ;u32_row != 0; u32_row -=2)
   1317     {
   1318         /* update working pointers */
   1319         pu8_yn  = pu8_y_data;
   1320         pu8_ys  = pu8_yn + u32_stride_Y;
   1321 
   1322         pu8_u   = pu8_u_data;
   1323         pu8_v   = pu8_v_data;
   1324 
   1325         pu8_rgbn= pu8_rgbn_data;
   1326 
   1327         /* loop on each column of the output image*/
   1328         for (u32_col = u32_width; u32_col != 0 ; u32_col -=2)
   1329         {
   1330             /* get RGB samples of 4 pixels */
   1331             GET_RGB24(i32_r00, i32_g00, i32_b00, pu8_rgbn, 0);
   1332             GET_RGB24(i32_r10, i32_g10, i32_b10, pu8_rgbn, CST_RGB_24_SIZE);
   1333             GET_RGB24(i32_r01, i32_g01, i32_b01, pu8_rgbn, u32_stride_rgb);
   1334             GET_RGB24(i32_r11, i32_g11, i32_b11, pu8_rgbn, u32_stride_rgb + CST_RGB_24_SIZE);
   1335 
   1336             i32_u00 = U24(i32_r00, i32_g00, i32_b00);
   1337             i32_v00 = V24(i32_r00, i32_g00, i32_b00);
   1338             i32_y00 = Y24(i32_r00, i32_g00, i32_b00);       /* matrix luminance */
   1339             pu8_yn[0]= (M4VIFI_UInt8)i32_y00;
   1340 
   1341             i32_u10 = U24(i32_r10, i32_g10, i32_b10);
   1342             i32_v10 = V24(i32_r10, i32_g10, i32_b10);
   1343             i32_y10 = Y24(i32_r10, i32_g10, i32_b10);
   1344             pu8_yn[1]= (M4VIFI_UInt8)i32_y10;
   1345 
   1346             i32_u01 = U24(i32_r01, i32_g01, i32_b01);
   1347             i32_v01 = V24(i32_r01, i32_g01, i32_b01);
   1348             i32_y01 = Y24(i32_r01, i32_g01, i32_b01);
   1349             pu8_ys[0]= (M4VIFI_UInt8)i32_y01;
   1350 
   1351             i32_u11 = U24(i32_r11, i32_g11, i32_b11);
   1352             i32_v11 = V24(i32_r11, i32_g11, i32_b11);
   1353             i32_y11 = Y24(i32_r11, i32_g11, i32_b11);
   1354             pu8_ys[1] = (M4VIFI_UInt8)i32_y11;
   1355 
   1356             *pu8_u  = (M4VIFI_UInt8)((i32_u00 + i32_u01 + i32_u10 + i32_u11 + 2) >> 2);
   1357             *pu8_v  = (M4VIFI_UInt8)((i32_v00 + i32_v01 + i32_v10 + i32_v11 + 2) >> 2);
   1358 
   1359             pu8_rgbn    +=  (CST_RGB_24_SIZE<<1);
   1360             pu8_yn      += 2;
   1361             pu8_ys      += 2;
   1362 
   1363             pu8_u ++;
   1364             pu8_v ++;
   1365         } /* end of horizontal scanning */
   1366 
   1367         pu8_y_data      += u32_stride2_Y;
   1368         pu8_u_data      += u32_stride_U;
   1369         pu8_v_data      += u32_stride_V;
   1370         pu8_rgbn_data   += u32_stride_2rgb;
   1371 
   1372 
   1373     } /* End of vertical scanning */
   1374 
   1375     return M4VIFI_OK;
   1376 }
   1377 
   1378 /** YUV420 to YUV420 */
   1379 /**
   1380  *******************************************************************************************
   1381  * M4VIFI_UInt8 M4VIFI_YUV420toYUV420 (void *pUserData,
   1382  *                                     M4VIFI_ImagePlane *pPlaneIn,
   1383  *                                     M4VIFI_ImagePlane *pPlaneOut)
   1384  * @brief   Transform YUV420 image to a YUV420 image.
   1385  * @param   pUserData: (IN) User Specific Data (Unused - could be NULL)
   1386  * @param   pPlaneIn: (IN) Pointer to YUV plane buffer
   1387  * @param   pPlaneOut: (OUT) Pointer to YUV Plane
   1388  * @return  M4VIFI_OK: there is no error
   1389  * @return  M4VIFI_ILLEGAL_FRAME_HEIGHT: Error in plane height
   1390  * @return  M4VIFI_ILLEGAL_FRAME_WIDTH:  Error in plane width
   1391  *******************************************************************************************
   1392  */
   1393 
   1394 M4VIFI_UInt8 M4VIFI_YUV420toYUV420(void *user_data, M4VIFI_ImagePlane PlaneIn[3], M4VIFI_ImagePlane *PlaneOut )
   1395 {
   1396     M4VIFI_Int32 plane_number;
   1397     M4VIFI_UInt32 i;
   1398     M4VIFI_UInt8 *p_buf_src, *p_buf_dest;
   1399 
   1400     for (plane_number = 0; plane_number < 3; plane_number++)
   1401     {
   1402         p_buf_src = &(PlaneIn[plane_number].pac_data[PlaneIn[plane_number].u_topleft]);
   1403         p_buf_dest = &(PlaneOut[plane_number].pac_data[PlaneOut[plane_number].u_topleft]);
   1404         for (i = 0; i < PlaneOut[plane_number].u_height; i++)
   1405         {
   1406             memcpy((void *)p_buf_dest, (void *)p_buf_src ,PlaneOut[plane_number].u_width);
   1407             p_buf_src += PlaneIn[plane_number].u_stride;
   1408             p_buf_dest += PlaneOut[plane_number].u_stride;
   1409         }
   1410     }
   1411     return M4VIFI_OK;
   1412 }
   1413 
   1414 /**
   1415  ***********************************************************************************************
   1416  * M4VIFI_UInt8 M4VIFI_ResizeBilinearYUV420toYUV420(void *pUserData, M4VIFI_ImagePlane *pPlaneIn,
   1417  *                                                                  M4VIFI_ImagePlane *pPlaneOut)
   1418  * @author  David Dana (PHILIPS Software)
   1419  * @brief   Resizes YUV420 Planar plane.
   1420  * @note    Basic structure of the function
   1421  *          Loop on each row (step 2)
   1422  *              Loop on each column (step 2)
   1423  *                  Get four Y samples and 1 U & V sample
   1424  *                  Resize the Y with corresponing U and V samples
   1425  *                  Place the YUV in the ouput plane
   1426  *              end loop column
   1427  *          end loop row
   1428  *          For resizing bilinear interpolation linearly interpolates along
   1429  *          each row, and then uses that result in a linear interpolation down each column.
   1430  *          Each estimated pixel in the output image is a weighted
   1431  *          combination of its four neighbours. The ratio of compression
   1432  *          or dilatation is estimated using input and output sizes.
   1433  * @param   pUserData: (IN) User Data
   1434  * @param   pPlaneIn: (IN) Pointer to YUV420 (Planar) plane buffer
   1435  * @param   pPlaneOut: (OUT) Pointer to YUV420 (Planar) plane
   1436  * @return  M4VIFI_OK: there is no error
   1437  * @return  M4VIFI_ILLEGAL_FRAME_HEIGHT: Error in height
   1438  * @return  M4VIFI_ILLEGAL_FRAME_WIDTH:  Error in width
   1439  ***********************************************************************************************
   1440 */
   1441 M4VIFI_UInt8    M4VIFI_ResizeBilinearYUV420toYUV420(void *pUserData,
   1442                                                                 M4VIFI_ImagePlane *pPlaneIn,
   1443                                                                 M4VIFI_ImagePlane *pPlaneOut)
   1444 {
   1445     M4VIFI_UInt8    *pu8_data_in, *pu8_data_out, *pu8dum;
   1446     M4VIFI_UInt32   u32_plane;
   1447     M4VIFI_UInt32   u32_width_in, u32_width_out, u32_height_in, u32_height_out;
   1448     M4VIFI_UInt32   u32_stride_in, u32_stride_out;
   1449     M4VIFI_UInt32   u32_x_inc, u32_y_inc;
   1450     M4VIFI_UInt32   u32_x_accum, u32_y_accum, u32_x_accum_start;
   1451     M4VIFI_UInt32   u32_width, u32_height;
   1452     M4VIFI_UInt32   u32_y_frac;
   1453     M4VIFI_UInt32   u32_x_frac;
   1454     M4VIFI_UInt32   u32_temp_value;
   1455     M4VIFI_UInt8    *pu8_src_top;
   1456     M4VIFI_UInt8    *pu8_src_bottom;
   1457 
   1458     M4VIFI_UInt8    u8Wflag = 0;
   1459     M4VIFI_UInt8    u8Hflag = 0;
   1460     M4VIFI_UInt32   loop = 0;
   1461 
   1462 
   1463     /*
   1464      If input width is equal to output width and input height equal to
   1465      output height then M4VIFI_YUV420toYUV420 is called.
   1466     */
   1467     if ((pPlaneIn[0].u_height == pPlaneOut[0].u_height) &&
   1468               (pPlaneIn[0].u_width == pPlaneOut[0].u_width))
   1469     {
   1470         return M4VIFI_YUV420toYUV420(pUserData, pPlaneIn, pPlaneOut);
   1471     }
   1472 
   1473     /* Check for the YUV width and height are even */
   1474     if ((IS_EVEN(pPlaneIn[0].u_height) == FALSE)    ||
   1475         (IS_EVEN(pPlaneOut[0].u_height) == FALSE))
   1476     {
   1477         return M4VIFI_ILLEGAL_FRAME_HEIGHT;
   1478     }
   1479 
   1480     if ((IS_EVEN(pPlaneIn[0].u_width) == FALSE) ||
   1481         (IS_EVEN(pPlaneOut[0].u_width) == FALSE))
   1482     {
   1483         return M4VIFI_ILLEGAL_FRAME_WIDTH;
   1484     }
   1485 
   1486     /* Loop on planes */
   1487     for(u32_plane = 0;u32_plane < PLANES;u32_plane++)
   1488     {
   1489         /* Set the working pointers at the beginning of the input/output data field */
   1490         pu8_data_in     = pPlaneIn[u32_plane].pac_data + pPlaneIn[u32_plane].u_topleft;
   1491         pu8_data_out    = pPlaneOut[u32_plane].pac_data + pPlaneOut[u32_plane].u_topleft;
   1492 
   1493         /* Get the memory jump corresponding to a row jump */
   1494         u32_stride_in   = pPlaneIn[u32_plane].u_stride;
   1495         u32_stride_out  = pPlaneOut[u32_plane].u_stride;
   1496 
   1497         /* Set the bounds of the active image */
   1498         u32_width_in    = pPlaneIn[u32_plane].u_width;
   1499         u32_height_in   = pPlaneIn[u32_plane].u_height;
   1500 
   1501         u32_width_out   = pPlaneOut[u32_plane].u_width;
   1502         u32_height_out  = pPlaneOut[u32_plane].u_height;
   1503 
   1504         /*
   1505         For the case , width_out = width_in , set the flag to avoid
   1506         accessing one column beyond the input width.In this case the last
   1507         column is replicated for processing
   1508         */
   1509         if (u32_width_out == u32_width_in) {
   1510             u32_width_out = u32_width_out-1;
   1511             u8Wflag = 1;
   1512         }
   1513 
   1514         /* Compute horizontal ratio between src and destination width.*/
   1515         if (u32_width_out >= u32_width_in)
   1516         {
   1517             u32_x_inc   = ((u32_width_in-1) * MAX_SHORT) / (u32_width_out-1);
   1518         }
   1519         else
   1520         {
   1521             u32_x_inc   = (u32_width_in * MAX_SHORT) / (u32_width_out);
   1522         }
   1523 
   1524         /*
   1525         For the case , height_out = height_in , set the flag to avoid
   1526         accessing one row beyond the input height.In this case the last
   1527         row is replicated for processing
   1528         */
   1529         if (u32_height_out == u32_height_in) {
   1530             u32_height_out = u32_height_out-1;
   1531             u8Hflag = 1;
   1532         }
   1533 
   1534         /* Compute vertical ratio between src and destination height.*/
   1535         if (u32_height_out >= u32_height_in)
   1536         {
   1537             u32_y_inc   = ((u32_height_in - 1) * MAX_SHORT) / (u32_height_out-1);
   1538         }
   1539         else
   1540         {
   1541             u32_y_inc = (u32_height_in * MAX_SHORT) / (u32_height_out);
   1542         }
   1543 
   1544         /*
   1545         Calculate initial accumulator value : u32_y_accum_start.
   1546         u32_y_accum_start is coded on 15 bits, and represents a value
   1547         between 0 and 0.5
   1548         */
   1549         if (u32_y_inc >= MAX_SHORT)
   1550         {
   1551         /*
   1552         Keep the fractionnal part, assimung that integer  part is coded
   1553         on the 16 high bits and the fractional on the 15 low bits
   1554         */
   1555             u32_y_accum = u32_y_inc & 0xffff;
   1556 
   1557             if (!u32_y_accum)
   1558             {
   1559                 u32_y_accum = MAX_SHORT;
   1560             }
   1561 
   1562             u32_y_accum >>= 1;
   1563         }
   1564         else
   1565         {
   1566             u32_y_accum = 0;
   1567         }
   1568 
   1569 
   1570         /*
   1571         Calculate initial accumulator value : u32_x_accum_start.
   1572         u32_x_accum_start is coded on 15 bits, and represents a value
   1573         between 0 and 0.5
   1574         */
   1575         if (u32_x_inc >= MAX_SHORT)
   1576         {
   1577             u32_x_accum_start = u32_x_inc & 0xffff;
   1578 
   1579             if (!u32_x_accum_start)
   1580             {
   1581                 u32_x_accum_start = MAX_SHORT;
   1582             }
   1583 
   1584             u32_x_accum_start >>= 1;
   1585         }
   1586         else
   1587         {
   1588             u32_x_accum_start = 0;
   1589         }
   1590 
   1591         u32_height = u32_height_out;
   1592 
   1593         /*
   1594         Bilinear interpolation linearly interpolates along each row, and
   1595         then uses that result in a linear interpolation donw each column.
   1596         Each estimated pixel in the output image is a weighted combination
   1597         of its four neighbours according to the formula:
   1598         F(p',q')=f(p,q)R(-a)R(b)+f(p,q-1)R(-a)R(b-1)+f(p+1,q)R(1-a)R(b)+
   1599         f(p+&,q+1)R(1-a)R(b-1) with  R(x) = / x+1  -1 =< x =< 0 \ 1-x
   1600         0 =< x =< 1 and a (resp. b)weighting coefficient is the distance
   1601         from the nearest neighbor in the p (resp. q) direction
   1602         */
   1603 
   1604         do { /* Scan all the row */
   1605 
   1606             /* Vertical weight factor */
   1607             u32_y_frac = (u32_y_accum>>12)&15;
   1608 
   1609             /* Reinit accumulator */
   1610             u32_x_accum = u32_x_accum_start;
   1611 
   1612             u32_width = u32_width_out;
   1613 
   1614             do { /* Scan along each row */
   1615                 pu8_src_top = pu8_data_in + (u32_x_accum >> 16);
   1616                 pu8_src_bottom = pu8_src_top + u32_stride_in;
   1617                 u32_x_frac = (u32_x_accum >> 12)&15; /* Horizontal weight factor */
   1618 
   1619                 /* Weighted combination */
   1620                 u32_temp_value = (M4VIFI_UInt8)(((pu8_src_top[0]*(16-u32_x_frac) +
   1621                                                  pu8_src_top[1]*u32_x_frac)*(16-u32_y_frac) +
   1622                                                 (pu8_src_bottom[0]*(16-u32_x_frac) +
   1623                                                  pu8_src_bottom[1]*u32_x_frac)*u32_y_frac )>>8);
   1624 
   1625                 *pu8_data_out++ = (M4VIFI_UInt8)u32_temp_value;
   1626 
   1627                 /* Update horizontal accumulator */
   1628                 u32_x_accum += u32_x_inc;
   1629             } while(--u32_width);
   1630 
   1631             /*
   1632                This u8Wflag flag gets in to effect if input and output
   1633                width is same, and height may be different. So previous
   1634                pixel is replicated here
   1635             */
   1636             if (u8Wflag) {
   1637                 *pu8_data_out = (M4VIFI_UInt8)u32_temp_value;
   1638             }
   1639 
   1640             pu8dum = (pu8_data_out-u32_width_out);
   1641             pu8_data_out = pu8_data_out + u32_stride_out - u32_width_out;
   1642 
   1643             /* Update vertical accumulator */
   1644             u32_y_accum += u32_y_inc;
   1645             if (u32_y_accum>>16) {
   1646                 pu8_data_in = pu8_data_in + (u32_y_accum >> 16) * u32_stride_in;
   1647                 u32_y_accum &= 0xffff;
   1648             }
   1649         } while(--u32_height);
   1650 
   1651         /*
   1652         This u8Hflag flag gets in to effect if input and output height
   1653         is same, and width may be different. So previous pixel row is
   1654         replicated here
   1655         */
   1656         if (u8Hflag) {
   1657             for(loop =0; loop < (u32_width_out+u8Wflag); loop++) {
   1658                 *pu8_data_out++ = (M4VIFI_UInt8)*pu8dum++;
   1659             }
   1660         }
   1661     }
   1662 
   1663     return M4VIFI_OK;
   1664 }
   1665 
   1666 M4OSA_ERR applyRenderingMode(M4VIFI_ImagePlane* pPlaneIn, M4VIFI_ImagePlane* pPlaneOut, M4xVSS_MediaRendering mediaRendering)
   1667 {
   1668     M4OSA_ERR err = M4NO_ERROR;
   1669 
   1670     if(mediaRendering == M4xVSS_kResizing)
   1671     {
   1672         /**
   1673          * Call the resize filter. From the intermediate frame to the encoder image plane */
   1674         err = M4VIFI_ResizeBilinearYUV420toYUV420(M4OSA_NULL, pPlaneIn, pPlaneOut);
   1675         if (M4NO_ERROR != err)
   1676         {
   1677             M4OSA_TRACE1_1("applyRenderingMode: M4ViFilResizeBilinearYUV420toYUV420 returns 0x%x!", err);
   1678             return err;
   1679         }
   1680     }
   1681     else
   1682     {
   1683         M4AIR_Params Params;
   1684         M4OSA_Context m_air_context;
   1685         M4VIFI_ImagePlane pImagePlanesTemp[3];
   1686         M4VIFI_ImagePlane* pPlaneTemp;
   1687         M4OSA_UInt8* pOutPlaneY = pPlaneOut[0].pac_data + pPlaneOut[0].u_topleft;
   1688         M4OSA_UInt8* pOutPlaneU = pPlaneOut[1].pac_data + pPlaneOut[1].u_topleft;
   1689         M4OSA_UInt8* pOutPlaneV = pPlaneOut[2].pac_data + pPlaneOut[2].u_topleft;
   1690         M4OSA_UInt8* pInPlaneY = NULL;
   1691         M4OSA_UInt8* pInPlaneU = NULL;
   1692         M4OSA_UInt8* pInPlaneV = NULL;
   1693         M4OSA_UInt32 i;
   1694 
   1695         /*to keep media aspect ratio*/
   1696         /*Initialize AIR Params*/
   1697         Params.m_inputCoord.m_x = 0;
   1698         Params.m_inputCoord.m_y = 0;
   1699         Params.m_inputSize.m_height = pPlaneIn->u_height;
   1700         Params.m_inputSize.m_width = pPlaneIn->u_width;
   1701         Params.m_outputSize.m_width = pPlaneOut->u_width;
   1702         Params.m_outputSize.m_height = pPlaneOut->u_height;
   1703         Params.m_bOutputStripe = M4OSA_FALSE;
   1704         Params.m_outputOrientation = M4COMMON_kOrientationTopLeft;
   1705 
   1706         /**
   1707         Media rendering: Black borders*/
   1708         if(mediaRendering == M4xVSS_kBlackBorders)
   1709         {
   1710             memset((void *)pPlaneOut[0].pac_data,Y_PLANE_BORDER_VALUE,(pPlaneOut[0].u_height*pPlaneOut[0].u_stride));
   1711             memset((void *)pPlaneOut[1].pac_data,U_PLANE_BORDER_VALUE,(pPlaneOut[1].u_height*pPlaneOut[1].u_stride));
   1712             memset((void *)pPlaneOut[2].pac_data,V_PLANE_BORDER_VALUE,(pPlaneOut[2].u_height*pPlaneOut[2].u_stride));
   1713 
   1714             pImagePlanesTemp[0].u_width = pPlaneOut[0].u_width;
   1715             pImagePlanesTemp[0].u_height = pPlaneOut[0].u_height;
   1716             pImagePlanesTemp[0].u_stride = pPlaneOut[0].u_width;
   1717             pImagePlanesTemp[0].u_topleft = 0;
   1718             pImagePlanesTemp[0].pac_data = M4OSA_NULL;
   1719 
   1720             pImagePlanesTemp[1].u_width = pPlaneOut[1].u_width;
   1721             pImagePlanesTemp[1].u_height = pPlaneOut[1].u_height;
   1722             pImagePlanesTemp[1].u_stride = pPlaneOut[1].u_width;
   1723             pImagePlanesTemp[1].u_topleft = 0;
   1724             pImagePlanesTemp[1].pac_data = M4OSA_NULL;
   1725 
   1726             pImagePlanesTemp[2].u_width = pPlaneOut[2].u_width;
   1727             pImagePlanesTemp[2].u_height = pPlaneOut[2].u_height;
   1728             pImagePlanesTemp[2].u_stride = pPlaneOut[2].u_width;
   1729             pImagePlanesTemp[2].u_topleft = 0;
   1730             pImagePlanesTemp[2].pac_data = M4OSA_NULL;
   1731 
   1732             /* Allocates plan in local image plane structure */
   1733             pImagePlanesTemp[0].pac_data = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(pImagePlanesTemp[0].u_width * pImagePlanesTemp[0].u_height, M4VS, (M4OSA_Char*)"applyRenderingMode: temporary plane bufferY") ;
   1734             if(pImagePlanesTemp[0].pac_data == M4OSA_NULL)
   1735             {
   1736                 M4OSA_TRACE1_0("Error alloc in applyRenderingMode");
   1737                 return M4ERR_ALLOC;
   1738             }
   1739             pImagePlanesTemp[1].pac_data = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(pImagePlanesTemp[1].u_width * pImagePlanesTemp[1].u_height, M4VS, (M4OSA_Char*)"applyRenderingMode: temporary plane bufferU") ;
   1740             if(pImagePlanesTemp[1].pac_data == M4OSA_NULL)
   1741             {
   1742 
   1743                 M4OSA_TRACE1_0("Error alloc in applyRenderingMode");
   1744                 return M4ERR_ALLOC;
   1745             }
   1746             pImagePlanesTemp[2].pac_data = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(pImagePlanesTemp[2].u_width * pImagePlanesTemp[2].u_height, M4VS, (M4OSA_Char*)"applyRenderingMode: temporary plane bufferV") ;
   1747             if(pImagePlanesTemp[2].pac_data == M4OSA_NULL)
   1748             {
   1749 
   1750                 M4OSA_TRACE1_0("Error alloc in applyRenderingMode");
   1751                 return M4ERR_ALLOC;
   1752             }
   1753 
   1754             pInPlaneY = pImagePlanesTemp[0].pac_data ;
   1755             pInPlaneU = pImagePlanesTemp[1].pac_data ;
   1756             pInPlaneV = pImagePlanesTemp[2].pac_data ;
   1757 
   1758             memset((void *)pImagePlanesTemp[0].pac_data,Y_PLANE_BORDER_VALUE,(pImagePlanesTemp[0].u_height*pImagePlanesTemp[0].u_stride));
   1759             memset((void *)pImagePlanesTemp[1].pac_data,U_PLANE_BORDER_VALUE,(pImagePlanesTemp[1].u_height*pImagePlanesTemp[1].u_stride));
   1760             memset((void *)pImagePlanesTemp[2].pac_data,V_PLANE_BORDER_VALUE,(pImagePlanesTemp[2].u_height*pImagePlanesTemp[2].u_stride));
   1761 
   1762             if((M4OSA_UInt32)((pPlaneIn->u_height * pPlaneOut->u_width) /pPlaneIn->u_width) <= pPlaneOut->u_height)//Params.m_inputSize.m_height < Params.m_inputSize.m_width)
   1763             {
   1764                 /*it is height so black borders will be on the top and on the bottom side*/
   1765                 Params.m_outputSize.m_width = pPlaneOut->u_width;
   1766                 Params.m_outputSize.m_height = (M4OSA_UInt32)((pPlaneIn->u_height * pPlaneOut->u_width) /pPlaneIn->u_width);
   1767                 /*number of lines at the top*/
   1768                 pImagePlanesTemp[0].u_topleft = (M4xVSS_ABS((M4OSA_Int32)(pImagePlanesTemp[0].u_height-Params.m_outputSize.m_height)>>1))*pImagePlanesTemp[0].u_stride;
   1769                 pImagePlanesTemp[0].u_height = Params.m_outputSize.m_height;
   1770                 pImagePlanesTemp[1].u_topleft = (M4xVSS_ABS((M4OSA_Int32)(pImagePlanesTemp[1].u_height-(Params.m_outputSize.m_height>>1)))>>1)*pImagePlanesTemp[1].u_stride;
   1771                 pImagePlanesTemp[1].u_height = Params.m_outputSize.m_height>>1;
   1772                 pImagePlanesTemp[2].u_topleft = (M4xVSS_ABS((M4OSA_Int32)(pImagePlanesTemp[2].u_height-(Params.m_outputSize.m_height>>1)))>>1)*pImagePlanesTemp[2].u_stride;
   1773                 pImagePlanesTemp[2].u_height = Params.m_outputSize.m_height>>1;
   1774             }
   1775             else
   1776             {
   1777                 /*it is width so black borders will be on the left and right side*/
   1778                 Params.m_outputSize.m_height = pPlaneOut->u_height;
   1779                 Params.m_outputSize.m_width = (M4OSA_UInt32)((pPlaneIn->u_width * pPlaneOut->u_height) /pPlaneIn->u_height);
   1780 
   1781                 pImagePlanesTemp[0].u_topleft = (M4xVSS_ABS((M4OSA_Int32)(pImagePlanesTemp[0].u_width-Params.m_outputSize.m_width)>>1));
   1782                 pImagePlanesTemp[0].u_width = Params.m_outputSize.m_width;
   1783                 pImagePlanesTemp[1].u_topleft = (M4xVSS_ABS((M4OSA_Int32)(pImagePlanesTemp[1].u_width-(Params.m_outputSize.m_width>>1)))>>1);
   1784                 pImagePlanesTemp[1].u_width = Params.m_outputSize.m_width>>1;
   1785                 pImagePlanesTemp[2].u_topleft = (M4xVSS_ABS((M4OSA_Int32)(pImagePlanesTemp[2].u_width-(Params.m_outputSize.m_width>>1)))>>1);
   1786                 pImagePlanesTemp[2].u_width = Params.m_outputSize.m_width>>1;
   1787             }
   1788 
   1789             /*Width and height have to be even*/
   1790             Params.m_outputSize.m_width = (Params.m_outputSize.m_width>>1)<<1;
   1791             Params.m_outputSize.m_height = (Params.m_outputSize.m_height>>1)<<1;
   1792             Params.m_inputSize.m_width = (Params.m_inputSize.m_width>>1)<<1;
   1793             Params.m_inputSize.m_height = (Params.m_inputSize.m_height>>1)<<1;
   1794             pImagePlanesTemp[0].u_width = (pImagePlanesTemp[0].u_width>>1)<<1;
   1795             pImagePlanesTemp[1].u_width = (pImagePlanesTemp[1].u_width>>1)<<1;
   1796             pImagePlanesTemp[2].u_width = (pImagePlanesTemp[2].u_width>>1)<<1;
   1797             pImagePlanesTemp[0].u_height = (pImagePlanesTemp[0].u_height>>1)<<1;
   1798             pImagePlanesTemp[1].u_height = (pImagePlanesTemp[1].u_height>>1)<<1;
   1799             pImagePlanesTemp[2].u_height = (pImagePlanesTemp[2].u_height>>1)<<1;
   1800 
   1801             /*Check that values are coherent*/
   1802             if(Params.m_inputSize.m_height == Params.m_outputSize.m_height)
   1803             {
   1804                 Params.m_inputSize.m_width = Params.m_outputSize.m_width;
   1805             }
   1806             else if(Params.m_inputSize.m_width == Params.m_outputSize.m_width)
   1807             {
   1808                 Params.m_inputSize.m_height = Params.m_outputSize.m_height;
   1809             }
   1810             pPlaneTemp = pImagePlanesTemp;
   1811 
   1812 
   1813         }
   1814 
   1815         /**
   1816         Media rendering: Cropping*/
   1817         if(mediaRendering == M4xVSS_kCropping)
   1818         {
   1819             Params.m_outputSize.m_height = pPlaneOut->u_height;
   1820             Params.m_outputSize.m_width = pPlaneOut->u_width;
   1821             if((Params.m_outputSize.m_height * Params.m_inputSize.m_width) /Params.m_outputSize.m_width<Params.m_inputSize.m_height)
   1822             {
   1823                 /*height will be cropped*/
   1824                 Params.m_inputSize.m_height = (M4OSA_UInt32)((Params.m_outputSize.m_height * Params.m_inputSize.m_width) /Params.m_outputSize.m_width);
   1825                 Params.m_inputSize.m_height = (Params.m_inputSize.m_height>>1)<<1;
   1826                 Params.m_inputCoord.m_y = (M4OSA_Int32)((M4OSA_Int32)((pPlaneIn->u_height - Params.m_inputSize.m_height))>>1);
   1827             }
   1828             else
   1829             {
   1830                 /*width will be cropped*/
   1831                 Params.m_inputSize.m_width = (M4OSA_UInt32)((Params.m_outputSize.m_width * Params.m_inputSize.m_height) /Params.m_outputSize.m_height);
   1832                 Params.m_inputSize.m_width = (Params.m_inputSize.m_width>>1)<<1;
   1833                 Params.m_inputCoord.m_x = (M4OSA_Int32)((M4OSA_Int32)((pPlaneIn->u_width - Params.m_inputSize.m_width))>>1);
   1834             }
   1835             pPlaneTemp = pPlaneOut;
   1836         }
   1837 
   1838         /**
   1839          * Call AIR functions */
   1840         err = M4AIR_create(&m_air_context, M4AIR_kYUV420P);
   1841         if(err != M4NO_ERROR)
   1842         {
   1843 
   1844             M4OSA_TRACE1_1("applyRenderingMode: Error when initializing AIR: 0x%x", err);
   1845             for(i=0; i<3; i++)
   1846             {
   1847                 if(pImagePlanesTemp[i].pac_data != M4OSA_NULL)
   1848                 {
   1849                     free(pImagePlanesTemp[i].pac_data);
   1850                     pImagePlanesTemp[i].pac_data = M4OSA_NULL;
   1851                 }
   1852             }
   1853             return err;
   1854         }
   1855 
   1856 
   1857         err = M4AIR_configure(m_air_context, &Params);
   1858         if(err != M4NO_ERROR)
   1859         {
   1860 
   1861             M4OSA_TRACE1_1("applyRenderingMode: Error when configuring AIR: 0x%x", err);
   1862             M4AIR_cleanUp(m_air_context);
   1863             for(i=0; i<3; i++)
   1864             {
   1865                 if(pImagePlanesTemp[i].pac_data != M4OSA_NULL)
   1866                 {
   1867                     free(pImagePlanesTemp[i].pac_data);
   1868                     pImagePlanesTemp[i].pac_data = M4OSA_NULL;
   1869                 }
   1870             }
   1871             return err;
   1872         }
   1873 
   1874         err = M4AIR_get(m_air_context, pPlaneIn, pPlaneTemp);
   1875         if(err != M4NO_ERROR)
   1876         {
   1877             M4OSA_TRACE1_1("applyRenderingMode: Error when getting AIR plane: 0x%x", err);
   1878             M4AIR_cleanUp(m_air_context);
   1879             for(i=0; i<3; i++)
   1880             {
   1881                 if(pImagePlanesTemp[i].pac_data != M4OSA_NULL)
   1882                 {
   1883                     free(pImagePlanesTemp[i].pac_data);
   1884                     pImagePlanesTemp[i].pac_data = M4OSA_NULL;
   1885                 }
   1886             }
   1887             return err;
   1888         }
   1889 
   1890         if(mediaRendering == M4xVSS_kBlackBorders)
   1891         {
   1892             for(i=0; i<pPlaneOut[0].u_height; i++)
   1893             {
   1894                 memcpy((void *)pOutPlaneY, (void *)pInPlaneY, pPlaneOut[0].u_width);
   1895                 pInPlaneY += pPlaneOut[0].u_width;
   1896                 pOutPlaneY += pPlaneOut[0].u_stride;
   1897             }
   1898             for(i=0; i<pPlaneOut[1].u_height; i++)
   1899             {
   1900                 memcpy((void *)pOutPlaneU, (void *)pInPlaneU, pPlaneOut[1].u_width);
   1901                 pInPlaneU += pPlaneOut[1].u_width;
   1902                 pOutPlaneU += pPlaneOut[1].u_stride;
   1903             }
   1904             for(i=0; i<pPlaneOut[2].u_height; i++)
   1905             {
   1906                 memcpy((void *)pOutPlaneV, (void *)pInPlaneV, pPlaneOut[2].u_width);
   1907                 pInPlaneV += pPlaneOut[2].u_width;
   1908                 pOutPlaneV += pPlaneOut[2].u_stride;
   1909             }
   1910 
   1911             for(i=0; i<3; i++)
   1912             {
   1913                 if(pImagePlanesTemp[i].pac_data != M4OSA_NULL)
   1914                 {
   1915                     free(pImagePlanesTemp[i].pac_data);
   1916                     pImagePlanesTemp[i].pac_data = M4OSA_NULL;
   1917                 }
   1918             }
   1919         }
   1920 
   1921         if (m_air_context != M4OSA_NULL) {
   1922             M4AIR_cleanUp(m_air_context);
   1923             m_air_context = M4OSA_NULL;
   1924         }
   1925     }
   1926 
   1927     return err;
   1928 }
   1929 
   1930 //TODO: remove this code after link with videoartist lib
   1931 /* M4AIR code*/
   1932 #define M4AIR_YUV420_FORMAT_SUPPORTED
   1933 #define M4AIR_YUV420A_FORMAT_SUPPORTED
   1934 
   1935 /************************* COMPILATION CHECKS ***************************/
   1936 #ifndef M4AIR_YUV420_FORMAT_SUPPORTED
   1937 #ifndef M4AIR_BGR565_FORMAT_SUPPORTED
   1938 #ifndef M4AIR_RGB565_FORMAT_SUPPORTED
   1939 #ifndef M4AIR_BGR888_FORMAT_SUPPORTED
   1940 #ifndef M4AIR_RGB888_FORMAT_SUPPORTED
   1941 #ifndef M4AIR_JPG_FORMAT_SUPPORTED
   1942 
   1943 #error "Please define at least one input format for the AIR component"
   1944 
   1945 #endif
   1946 #endif
   1947 #endif
   1948 #endif
   1949 #endif
   1950 #endif
   1951 
   1952 /************************ M4AIR INTERNAL TYPES DEFINITIONS ***********************/
   1953 
   1954 /**
   1955  ******************************************************************************
   1956  * enum         M4AIR_States
   1957  * @brief       The following enumeration defines the internal states of the AIR.
   1958  ******************************************************************************
   1959 */
   1960 typedef enum
   1961 {
   1962     M4AIR_kCreated,         /**< State after M4AIR_create has been called */
   1963     M4AIR_kConfigured           /**< State after M4AIR_configure has been called */
   1964 }M4AIR_States;
   1965 
   1966 
   1967 /**
   1968  ******************************************************************************
   1969  * struct       M4AIR_InternalContext
   1970  * @brief       The following structure is the internal context of the AIR.
   1971  ******************************************************************************
   1972 */
   1973 typedef struct
   1974 {
   1975     M4AIR_States                m_state;            /**< Internal state */
   1976     M4AIR_InputFormatType   m_inputFormat;      /**< Input format like YUV420Planar, RGB565, JPG, etc ... */
   1977     M4AIR_Params            m_params;           /**< Current input Parameter of  the processing */
   1978     M4OSA_UInt32            u32_x_inc[4];       /**< ratio between input and ouput width for YUV */
   1979     M4OSA_UInt32            u32_y_inc[4];       /**< ratio between input and ouput height for YUV */
   1980     M4OSA_UInt32            u32_x_accum_start[4];   /**< horizontal initial accumulator value */
   1981     M4OSA_UInt32            u32_y_accum_start[4];   /**< Vertical initial accumulator value */
   1982     M4OSA_UInt32            u32_x_accum[4];     /**< save of horizontal accumulator value */
   1983     M4OSA_UInt32            u32_y_accum[4];     /**< save of vertical accumulator value */
   1984     M4OSA_UInt8*            pu8_data_in[4];         /**< Save of input plane pointers in case of stripe mode */
   1985     M4OSA_UInt32            m_procRows;         /**< Number of processed rows, used in stripe mode only */
   1986     M4OSA_Bool              m_bOnlyCopy;            /**< Flag to know if we just perform a copy or a bilinear interpolation */
   1987     M4OSA_Bool              m_bFlipX;               /**< Depend on output orientation, used during processing to revert processing order in X coordinates */
   1988     M4OSA_Bool              m_bFlipY;               /**< Depend on output orientation, used during processing to revert processing order in Y coordinates */
   1989     M4OSA_Bool              m_bRevertXY;            /**< Depend on output orientation, used during processing to revert X and Y processing order (+-90 rotation) */
   1990 }M4AIR_InternalContext;
   1991 
   1992 /********************************* MACROS *******************************/
   1993 #define M4ERR_CHECK_NULL_RETURN_VALUE(retval, pointer) if ((pointer) == M4OSA_NULL) return ((M4OSA_ERR)(retval));
   1994 
   1995 
   1996 /********************** M4AIR PUBLIC API IMPLEMENTATION ********************/
   1997 /**
   1998  ******************************************************************************
   1999  * M4OSA_ERR M4AIR_create(M4OSA_Context* pContext,M4AIR_InputFormatType inputFormat)
   2000  * @author  Arnaud Collard
   2001  * @brief       This function initialize an instance of the AIR.
   2002  * @param   pContext:   (IN/OUT) Address of the context to create
   2003  * @param   inputFormat:    (IN) input format type.
   2004  * @return  M4NO_ERROR: there is no error
   2005  * @return  M4ERR_PARAMETER: pContext is M4OSA_NULL (debug only). Invalid formatType
   2006  * @return  M4ERR_ALLOC: No more memory is available
   2007  ******************************************************************************
   2008 */
   2009 M4OSA_ERR M4AIR_create(M4OSA_Context* pContext,M4AIR_InputFormatType inputFormat)
   2010 {
   2011     M4OSA_ERR err = M4NO_ERROR ;
   2012     M4AIR_InternalContext* pC = M4OSA_NULL ;
   2013     /* Check that the address on the context is not NULL */
   2014     M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pContext) ;
   2015 
   2016     *pContext = M4OSA_NULL ;
   2017 
   2018     /* Internal Context creation */
   2019     pC = (M4AIR_InternalContext*)M4OSA_32bitAlignedMalloc(sizeof(M4AIR_InternalContext), M4AIR, (M4OSA_Char*)"AIR internal context") ;
   2020     M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_ALLOC, pC) ;
   2021 
   2022 
   2023     /* Check if the input format is supported */
   2024     switch(inputFormat)
   2025     {
   2026 #ifdef M4AIR_YUV420_FORMAT_SUPPORTED
   2027         case M4AIR_kYUV420P:
   2028         break ;
   2029 #endif
   2030 #ifdef M4AIR_YUV420A_FORMAT_SUPPORTED
   2031         case M4AIR_kYUV420AP:
   2032         break ;
   2033 #endif
   2034         default:
   2035             err = M4ERR_AIR_FORMAT_NOT_SUPPORTED;
   2036             goto M4AIR_create_cleanup ;
   2037     }
   2038 
   2039     /**< Save input format and update state */
   2040     pC->m_inputFormat = inputFormat;
   2041     pC->m_state = M4AIR_kCreated;
   2042 
   2043     /* Return the context to the caller */
   2044     *pContext = pC ;
   2045 
   2046     return M4NO_ERROR ;
   2047 
   2048 M4AIR_create_cleanup:
   2049     /* Error management : we destroy the context if needed */
   2050     if(M4OSA_NULL != pC)
   2051     {
   2052         free(pC) ;
   2053     }
   2054 
   2055     *pContext = M4OSA_NULL ;
   2056 
   2057     return err ;
   2058 }
   2059 
   2060 
   2061 
   2062 /**
   2063  ******************************************************************************
   2064  * M4OSA_ERR M4AIR_cleanUp(M4OSA_Context pContext)
   2065  * @author  Arnaud Collard
   2066  * @brief       This function destroys an instance of the AIR component
   2067  * @param   pContext:   (IN) Context identifying the instance to destroy
   2068  * @return  M4NO_ERROR: there is no error
   2069  * @return  M4ERR_PARAMETER: pContext is M4OSA_NULL (debug only).
   2070  * @return  M4ERR_STATE: Internal state is incompatible with this function call.
   2071 ******************************************************************************
   2072 */
   2073 M4OSA_ERR M4AIR_cleanUp(M4OSA_Context pContext)
   2074 {
   2075     M4AIR_InternalContext* pC = (M4AIR_InternalContext*)pContext ;
   2076 
   2077     M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pContext) ;
   2078 
   2079     /**< Check state */
   2080     if((M4AIR_kCreated != pC->m_state)&&(M4AIR_kConfigured != pC->m_state))
   2081     {
   2082         return M4ERR_STATE;
   2083     }
   2084     free(pC) ;
   2085 
   2086     return M4NO_ERROR ;
   2087 
   2088 }
   2089 
   2090 
   2091 /**
   2092  ******************************************************************************
   2093  * M4OSA_ERR M4AIR_configure(M4OSA_Context pContext, M4AIR_Params* pParams)
   2094  * @brief       This function will configure the AIR.
   2095  * @note    It will set the input and output coordinates and sizes,
   2096  *          and indicates if we will proceed in stripe or not.
   2097  *          In case a M4AIR_get in stripe mode was on going, it will cancel this previous processing
   2098  *          and reset the get process.
   2099  * @param   pContext:               (IN) Context identifying the instance
   2100  * @param   pParams->m_bOutputStripe:(IN) Stripe mode.
   2101  * @param   pParams->m_inputCoord:  (IN) X,Y coordinates of the first valid pixel in input.
   2102  * @param   pParams->m_inputSize:   (IN) input ROI size.
   2103  * @param   pParams->m_outputSize:  (IN) output size.
   2104  * @return  M4NO_ERROR: there is no error
   2105  * @return  M4ERR_ALLOC: No more memory space to add a new effect.
   2106  * @return  M4ERR_PARAMETER: pContext is M4OSA_NULL (debug only).
   2107  * @return  M4ERR_AIR_FORMAT_NOT_SUPPORTED: the requested input format is not supported.
   2108  ******************************************************************************
   2109 */
   2110 M4OSA_ERR M4AIR_configure(M4OSA_Context pContext, M4AIR_Params* pParams)
   2111 {
   2112     M4AIR_InternalContext* pC = (M4AIR_InternalContext*)pContext ;
   2113     M4OSA_UInt32    i,u32_width_in, u32_width_out, u32_height_in, u32_height_out;
   2114     M4OSA_UInt32    nb_planes;
   2115 
   2116     M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pContext) ;
   2117 
   2118     if(M4AIR_kYUV420AP == pC->m_inputFormat)
   2119     {
   2120         nb_planes = 4;
   2121     }
   2122     else
   2123     {
   2124         nb_planes = 3;
   2125     }
   2126 
   2127     /**< Check state */
   2128     if((M4AIR_kCreated != pC->m_state)&&(M4AIR_kConfigured != pC->m_state))
   2129     {
   2130         return M4ERR_STATE;
   2131     }
   2132 
   2133     /** Save parameters */
   2134     pC->m_params = *pParams;
   2135 
   2136     /* Check for the input&output width and height are even */
   2137         if( ((pC->m_params.m_inputSize.m_height)&0x1)    ||
   2138          ((pC->m_params.m_inputSize.m_height)&0x1))
   2139         {
   2140          return M4ERR_AIR_ILLEGAL_FRAME_SIZE;
   2141         }
   2142 
   2143     if( ((pC->m_params.m_inputSize.m_width)&0x1)    ||
   2144          ((pC->m_params.m_inputSize.m_width)&0x1))
   2145         {
   2146             return M4ERR_AIR_ILLEGAL_FRAME_SIZE;
   2147         }
   2148     if(((pC->m_params.m_inputSize.m_width) == (pC->m_params.m_outputSize.m_width))
   2149         &&((pC->m_params.m_inputSize.m_height) == (pC->m_params.m_outputSize.m_height)))
   2150     {
   2151         /**< No resize in this case, we will just copy input in output */
   2152         pC->m_bOnlyCopy = M4OSA_TRUE;
   2153     }
   2154     else
   2155     {
   2156         pC->m_bOnlyCopy = M4OSA_FALSE;
   2157 
   2158         /**< Initialize internal variables used for resize filter */
   2159         for(i=0;i<nb_planes;i++)
   2160         {
   2161 
   2162             u32_width_in = ((i==0)||(i==3))?pC->m_params.m_inputSize.m_width:(pC->m_params.m_inputSize.m_width+1)>>1;
   2163             u32_height_in = ((i==0)||(i==3))?pC->m_params.m_inputSize.m_height:(pC->m_params.m_inputSize.m_height+1)>>1;
   2164             u32_width_out = ((i==0)||(i==3))?pC->m_params.m_outputSize.m_width:(pC->m_params.m_outputSize.m_width+1)>>1;
   2165             u32_height_out = ((i==0)||(i==3))?pC->m_params.m_outputSize.m_height:(pC->m_params.m_outputSize.m_height+1)>>1;
   2166 
   2167                 /* Compute horizontal ratio between src and destination width.*/
   2168                 if (u32_width_out >= u32_width_in)
   2169                 {
   2170                     pC->u32_x_inc[i]   = ((u32_width_in-1) * 0x10000) / (u32_width_out-1);
   2171                 }
   2172                 else
   2173                 {
   2174                     pC->u32_x_inc[i]   = (u32_width_in * 0x10000) / (u32_width_out);
   2175                 }
   2176 
   2177                 /* Compute vertical ratio between src and destination height.*/
   2178                 if (u32_height_out >= u32_height_in)
   2179                 {
   2180                     pC->u32_y_inc[i]   = ((u32_height_in - 1) * 0x10000) / (u32_height_out-1);
   2181                 }
   2182                 else
   2183                 {
   2184                     pC->u32_y_inc[i] = (u32_height_in * 0x10000) / (u32_height_out);
   2185                 }
   2186 
   2187                 /*
   2188                 Calculate initial accumulator value : u32_y_accum_start.
   2189                 u32_y_accum_start is coded on 15 bits, and represents a value between 0 and 0.5
   2190                 */
   2191                 if (pC->u32_y_inc[i] >= 0x10000)
   2192                 {
   2193                     /*
   2194                         Keep the fractionnal part, assimung that integer  part is coded
   2195                         on the 16 high bits and the fractionnal on the 15 low bits
   2196                     */
   2197                     pC->u32_y_accum_start[i] = pC->u32_y_inc[i] & 0xffff;
   2198 
   2199                     if (!pC->u32_y_accum_start[i])
   2200                     {
   2201                         pC->u32_y_accum_start[i] = 0x10000;
   2202                     }
   2203 
   2204                     pC->u32_y_accum_start[i] >>= 1;
   2205                 }
   2206                 else
   2207                 {
   2208                     pC->u32_y_accum_start[i] = 0;
   2209                 }
   2210                 /**< Take into account that Y coordinate can be odd
   2211                     in this case we have to put a 0.5 offset
   2212                     for U and V plane as there a 2 times sub-sampled vs Y*/
   2213                 if((pC->m_params.m_inputCoord.m_y&0x1)&&((i==1)||(i==2)))
   2214                 {
   2215                     pC->u32_y_accum_start[i] += 0x8000;
   2216                 }
   2217 
   2218                 /*
   2219                     Calculate initial accumulator value : u32_x_accum_start.
   2220                     u32_x_accum_start is coded on 15 bits, and represents a value between 0 and 0.5
   2221                 */
   2222 
   2223                 if (pC->u32_x_inc[i] >= 0x10000)
   2224                 {
   2225                     pC->u32_x_accum_start[i] = pC->u32_x_inc[i] & 0xffff;
   2226 
   2227                     if (!pC->u32_x_accum_start[i])
   2228                     {
   2229                         pC->u32_x_accum_start[i] = 0x10000;
   2230                     }
   2231 
   2232                     pC->u32_x_accum_start[i] >>= 1;
   2233                 }
   2234                 else
   2235                 {
   2236                     pC->u32_x_accum_start[i] = 0;
   2237                 }
   2238                 /**< Take into account that X coordinate can be odd
   2239                     in this case we have to put a 0.5 offset
   2240                     for U and V plane as there a 2 times sub-sampled vs Y*/
   2241                 if((pC->m_params.m_inputCoord.m_x&0x1)&&((i==1)||(i==2)))
   2242                 {
   2243                     pC->u32_x_accum_start[i] += 0x8000;
   2244                 }
   2245         }
   2246     }
   2247 
   2248     /**< Reset variable used for stripe mode */
   2249     pC->m_procRows = 0;
   2250 
   2251     /**< Initialize var for X/Y processing order according to orientation */
   2252     pC->m_bFlipX = M4OSA_FALSE;
   2253     pC->m_bFlipY = M4OSA_FALSE;
   2254     pC->m_bRevertXY = M4OSA_FALSE;
   2255     switch(pParams->m_outputOrientation)
   2256     {
   2257         case M4COMMON_kOrientationTopLeft:
   2258             break;
   2259         case M4COMMON_kOrientationTopRight:
   2260             pC->m_bFlipX = M4OSA_TRUE;
   2261             break;
   2262         case M4COMMON_kOrientationBottomRight:
   2263             pC->m_bFlipX = M4OSA_TRUE;
   2264             pC->m_bFlipY = M4OSA_TRUE;
   2265             break;
   2266         case M4COMMON_kOrientationBottomLeft:
   2267             pC->m_bFlipY = M4OSA_TRUE;
   2268             break;
   2269         case M4COMMON_kOrientationLeftTop:
   2270             pC->m_bRevertXY = M4OSA_TRUE;
   2271             break;
   2272         case M4COMMON_kOrientationRightTop:
   2273             pC->m_bRevertXY = M4OSA_TRUE;
   2274             pC->m_bFlipY = M4OSA_TRUE;
   2275         break;
   2276         case M4COMMON_kOrientationRightBottom:
   2277             pC->m_bRevertXY = M4OSA_TRUE;
   2278             pC->m_bFlipX = M4OSA_TRUE;
   2279             pC->m_bFlipY = M4OSA_TRUE;
   2280             break;
   2281         case M4COMMON_kOrientationLeftBottom:
   2282             pC->m_bRevertXY = M4OSA_TRUE;
   2283             pC->m_bFlipX = M4OSA_TRUE;
   2284             break;
   2285         default:
   2286         return M4ERR_PARAMETER;
   2287     }
   2288     /**< Update state */
   2289     pC->m_state = M4AIR_kConfigured;
   2290 
   2291     return M4NO_ERROR ;
   2292 }
   2293 
   2294 
   2295 /**
   2296  ******************************************************************************
   2297  * M4OSA_ERR M4AIR_get(M4OSA_Context pContext, M4VIFI_ImagePlane* pIn, M4VIFI_ImagePlane* pOut)
   2298  * @brief   This function will provide the requested resized area of interest according to settings
   2299  *          provided in M4AIR_configure.
   2300  * @note    In case the input format type is JPEG, input plane(s)
   2301  *          in pIn is not used. In normal mode, dimension specified in output plane(s) structure must be the
   2302  *          same than the one specified in M4AIR_configure. In stripe mode, only the width will be the same,
   2303  *          height will be taken as the stripe height (typically 16).
   2304  *          In normal mode, this function is call once to get the full output picture. In stripe mode, it is called
   2305  *          for each stripe till the whole picture has been retrieved,and  the position of the output stripe in the output picture
   2306  *          is internally incremented at each step.
   2307  *          Any call to M4AIR_configure during stripe process will reset this one to the beginning of the output picture.
   2308  * @param   pContext:   (IN) Context identifying the instance
   2309  * @param   pIn:            (IN) Plane structure containing input Plane(s).
   2310  * @param   pOut:       (IN/OUT)  Plane structure containing output Plane(s).
   2311  * @return  M4NO_ERROR: there is no error
   2312  * @return  M4ERR_ALLOC: No more memory space to add a new effect.
   2313  * @return  M4ERR_PARAMETER: pContext is M4OSA_NULL (debug only).
   2314  ******************************************************************************
   2315 */
   2316 M4OSA_ERR M4AIR_get(M4OSA_Context pContext, M4VIFI_ImagePlane* pIn, M4VIFI_ImagePlane* pOut)
   2317 {
   2318     M4AIR_InternalContext* pC = (M4AIR_InternalContext*)pContext ;
   2319     M4OSA_UInt32 i,j,k,u32_x_frac,u32_y_frac,u32_x_accum,u32_y_accum,u32_shift;
   2320         M4OSA_UInt8    *pu8_data_in, *pu8_data_in_org, *pu8_data_in_tmp, *pu8_data_out;
   2321         M4OSA_UInt8    *pu8_src_top;
   2322         M4OSA_UInt8    *pu8_src_bottom;
   2323     M4OSA_UInt32    u32_temp_value;
   2324     M4OSA_Int32 i32_tmp_offset;
   2325     M4OSA_UInt32    nb_planes;
   2326 
   2327 
   2328 
   2329     M4ERR_CHECK_NULL_RETURN_VALUE(M4ERR_PARAMETER, pContext) ;
   2330 
   2331     /**< Check state */
   2332     if(M4AIR_kConfigured != pC->m_state)
   2333     {
   2334         return M4ERR_STATE;
   2335     }
   2336 
   2337     if(M4AIR_kYUV420AP == pC->m_inputFormat)
   2338     {
   2339         nb_planes = 4;
   2340     }
   2341     else
   2342     {
   2343         nb_planes = 3;
   2344     }
   2345 
   2346     /**< Loop on each Plane */
   2347     for(i=0;i<nb_planes;i++)
   2348     {
   2349 
   2350          /* Set the working pointers at the beginning of the input/output data field */
   2351 
   2352         u32_shift = ((i==0)||(i==3))?0:1; /**< Depend on Luma or Chroma */
   2353 
   2354         if((M4OSA_FALSE == pC->m_params.m_bOutputStripe)||((M4OSA_TRUE == pC->m_params.m_bOutputStripe)&&(0 == pC->m_procRows)))
   2355         {
   2356             /**< For input, take care about ROI */
   2357             pu8_data_in     = pIn[i].pac_data + pIn[i].u_topleft + (pC->m_params.m_inputCoord.m_x>>u32_shift)
   2358                         + (pC->m_params.m_inputCoord.m_y >> u32_shift) * pIn[i].u_stride;
   2359 
   2360             /** Go at end of line/column in case X/Y scanning is flipped */
   2361             if(M4OSA_TRUE == pC->m_bFlipX)
   2362             {
   2363                 pu8_data_in += ((pC->m_params.m_inputSize.m_width)>>u32_shift) -1 ;
   2364             }
   2365             if(M4OSA_TRUE == pC->m_bFlipY)
   2366             {
   2367                 pu8_data_in += ((pC->m_params.m_inputSize.m_height>>u32_shift) -1) * pIn[i].u_stride;
   2368             }
   2369 
   2370             /**< Initialize accumulators in case we are using it (bilinear interpolation) */
   2371             if( M4OSA_FALSE == pC->m_bOnlyCopy)
   2372             {
   2373                 pC->u32_x_accum[i] = pC->u32_x_accum_start[i];
   2374                 pC->u32_y_accum[i] = pC->u32_y_accum_start[i];
   2375             }
   2376 
   2377         }
   2378         else
   2379         {
   2380             /**< In case of stripe mode for other than first stripe, we need to recover input pointer from internal context */
   2381             pu8_data_in = pC->pu8_data_in[i];
   2382         }
   2383 
   2384         /**< In every mode, output data are at the beginning of the output plane */
   2385         pu8_data_out    = pOut[i].pac_data + pOut[i].u_topleft;
   2386 
   2387         /**< Initialize input offset applied after each pixel */
   2388         if(M4OSA_FALSE == pC->m_bFlipY)
   2389         {
   2390             i32_tmp_offset = pIn[i].u_stride;
   2391         }
   2392         else
   2393         {
   2394             i32_tmp_offset = -pIn[i].u_stride;
   2395         }
   2396 
   2397         /**< In this case, no bilinear interpolation is needed as input and output dimensions are the same */
   2398         if( M4OSA_TRUE == pC->m_bOnlyCopy)
   2399         {
   2400             /**< No +-90 rotation */
   2401             if(M4OSA_FALSE == pC->m_bRevertXY)
   2402             {
   2403                 /**< No flip on X abscissa */
   2404                 if(M4OSA_FALSE == pC->m_bFlipX)
   2405                 {
   2406                      M4OSA_UInt32 loc_height = pOut[i].u_height;
   2407                      M4OSA_UInt32 loc_width = pOut[i].u_width;
   2408                      M4OSA_UInt32 loc_stride = pIn[i].u_stride;
   2409                     /**< Loop on each row */
   2410                     for (j=0; j<loc_height; j++)
   2411                     {
   2412                         /**< Copy one whole line */
   2413                         memcpy((void *)pu8_data_out, (void *)pu8_data_in, loc_width);
   2414 
   2415                         /**< Update pointers */
   2416                         pu8_data_out += pOut[i].u_stride;
   2417                         if(M4OSA_FALSE == pC->m_bFlipY)
   2418                         {
   2419                             pu8_data_in += loc_stride;
   2420                         }
   2421                         else
   2422                         {
   2423                             pu8_data_in -= loc_stride;
   2424                         }
   2425                     }
   2426                 }
   2427                 else
   2428                 {
   2429                     /**< Loop on each row */
   2430                     for(j=0;j<pOut[i].u_height;j++)
   2431                     {
   2432                         /**< Loop on each pixel of 1 row */
   2433                         for(k=0;k<pOut[i].u_width;k++)
   2434                         {
   2435                             *pu8_data_out++ = *pu8_data_in--;
   2436                         }
   2437 
   2438                         /**< Update pointers */
   2439                         pu8_data_out += (pOut[i].u_stride - pOut[i].u_width);
   2440 
   2441                         pu8_data_in += pOut[i].u_width + i32_tmp_offset;
   2442 
   2443                     }
   2444                 }
   2445             }
   2446             /**< Here we have a +-90 rotation */
   2447             else
   2448             {
   2449 
   2450                 /**< Loop on each row */
   2451                 for(j=0;j<pOut[i].u_height;j++)
   2452                 {
   2453                     pu8_data_in_tmp = pu8_data_in;
   2454 
   2455                     /**< Loop on each pixel of 1 row */
   2456                     for(k=0;k<pOut[i].u_width;k++)
   2457                     {
   2458                         *pu8_data_out++ = *pu8_data_in_tmp;
   2459 
   2460                         /**< Update input pointer in order to go to next/past line */
   2461                         pu8_data_in_tmp += i32_tmp_offset;
   2462                     }
   2463 
   2464                     /**< Update pointers */
   2465                     pu8_data_out += (pOut[i].u_stride - pOut[i].u_width);
   2466                     if(M4OSA_FALSE == pC->m_bFlipX)
   2467                     {
   2468                         pu8_data_in ++;
   2469                     }
   2470                     else
   2471                     {
   2472                         pu8_data_in --;
   2473                     }
   2474                 }
   2475             }
   2476         }
   2477         /**< Bilinear interpolation */
   2478         else
   2479         {
   2480 
   2481         if(3 != i)  /**< other than alpha plane */
   2482         {
   2483             /**No +-90 rotation */
   2484             if(M4OSA_FALSE == pC->m_bRevertXY)
   2485             {
   2486 
   2487                 /**< Loop on each row */
   2488                 for(j=0;j<pOut[i].u_height;j++)
   2489                 {
   2490                     /* Vertical weight factor */
   2491                     u32_y_frac = (pC->u32_y_accum[i]>>12)&15;
   2492 
   2493                     /* Reinit horizontal weight factor */
   2494                     u32_x_accum = pC->u32_x_accum_start[i];
   2495 
   2496 
   2497 
   2498                         if(M4OSA_TRUE ==  pC->m_bFlipX)
   2499                         {
   2500 
   2501                             /**< Loop on each output pixel in a row */
   2502                             for(k=0;k<pOut[i].u_width;k++)
   2503                             {
   2504 
   2505                                 u32_x_frac = (u32_x_accum >> 12)&15; /* Fraction of Horizontal weight factor */
   2506 
   2507                                 pu8_src_top = (pu8_data_in - (u32_x_accum >> 16)) -1 ;
   2508 
   2509                                 pu8_src_bottom = pu8_src_top + i32_tmp_offset;
   2510 
   2511                                 /* Weighted combination */
   2512                                 u32_temp_value = (M4VIFI_UInt8)(((pu8_src_top[1]*(16-u32_x_frac) +
   2513                                                                  pu8_src_top[0]*u32_x_frac)*(16-u32_y_frac) +
   2514                                                                 (pu8_src_bottom[1]*(16-u32_x_frac) +
   2515                                                                  pu8_src_bottom[0]*u32_x_frac)*u32_y_frac )>>8);
   2516 
   2517                                 *pu8_data_out++ = (M4VIFI_UInt8)u32_temp_value;
   2518 
   2519                                 /* Update horizontal accumulator */
   2520                                 u32_x_accum += pC->u32_x_inc[i];
   2521                             }
   2522                         }
   2523 
   2524                         else
   2525                         {
   2526                             /**< Loop on each output pixel in a row */
   2527                             for(k=0;k<pOut[i].u_width;k++)
   2528                             {
   2529                                 u32_x_frac = (u32_x_accum >> 12)&15; /* Fraction of Horizontal weight factor */
   2530 
   2531                                 pu8_src_top = pu8_data_in + (u32_x_accum >> 16);
   2532 
   2533                                 pu8_src_bottom = pu8_src_top + i32_tmp_offset;
   2534 
   2535                                 /* Weighted combination */
   2536                                 u32_temp_value = (M4VIFI_UInt8)(((pu8_src_top[0]*(16-u32_x_frac) +
   2537                                                                  pu8_src_top[1]*u32_x_frac)*(16-u32_y_frac) +
   2538                                                                 (pu8_src_bottom[0]*(16-u32_x_frac) +
   2539                                                                  pu8_src_bottom[1]*u32_x_frac)*u32_y_frac )>>8);
   2540 
   2541                                     *pu8_data_out++ = (M4VIFI_UInt8)u32_temp_value;
   2542 
   2543                                 /* Update horizontal accumulator */
   2544                                 u32_x_accum += pC->u32_x_inc[i];
   2545                             }
   2546 
   2547                         }
   2548 
   2549                     pu8_data_out += pOut[i].u_stride - pOut[i].u_width;
   2550 
   2551                     /* Update vertical accumulator */
   2552                     pC->u32_y_accum[i] += pC->u32_y_inc[i];
   2553                     if (pC->u32_y_accum[i]>>16)
   2554                     {
   2555                         pu8_data_in = pu8_data_in + (pC->u32_y_accum[i] >> 16) * i32_tmp_offset;
   2556                         pC->u32_y_accum[i] &= 0xffff;
   2557                     }
   2558                 }
   2559         }
   2560             /** +-90 rotation */
   2561             else
   2562             {
   2563                 pu8_data_in_org = pu8_data_in;
   2564 
   2565                 /**< Loop on each output row */
   2566                 for(j=0;j<pOut[i].u_height;j++)
   2567                 {
   2568                     /* horizontal weight factor */
   2569                     u32_x_frac = (pC->u32_x_accum[i]>>12)&15;
   2570 
   2571                     /* Reinit accumulator */
   2572                     u32_y_accum = pC->u32_y_accum_start[i];
   2573 
   2574                     if(M4OSA_TRUE ==  pC->m_bFlipX)
   2575                     {
   2576 
   2577                         /**< Loop on each output pixel in a row */
   2578                         for(k=0;k<pOut[i].u_width;k++)
   2579                         {
   2580 
   2581                             u32_y_frac = (u32_y_accum >> 12)&15; /* Vertical weight factor */
   2582 
   2583 
   2584                             pu8_src_top = (pu8_data_in - (pC->u32_x_accum[i] >> 16)) - 1;
   2585 
   2586                             pu8_src_bottom = pu8_src_top + i32_tmp_offset;
   2587 
   2588                             /* Weighted combination */
   2589                             u32_temp_value = (M4VIFI_UInt8)(((pu8_src_top[1]*(16-u32_x_frac) +
   2590                                                                  pu8_src_top[0]*u32_x_frac)*(16-u32_y_frac) +
   2591                                                                 (pu8_src_bottom[1]*(16-u32_x_frac) +
   2592                                                                  pu8_src_bottom[0]*u32_x_frac)*u32_y_frac )>>8);
   2593 
   2594                             *pu8_data_out++ = (M4VIFI_UInt8)u32_temp_value;
   2595 
   2596                             /* Update vertical accumulator */
   2597                             u32_y_accum += pC->u32_y_inc[i];
   2598                             if (u32_y_accum>>16)
   2599                             {
   2600                                 pu8_data_in = pu8_data_in + (u32_y_accum >> 16) * i32_tmp_offset;
   2601                                 u32_y_accum &= 0xffff;
   2602                             }
   2603 
   2604                         }
   2605                     }
   2606                     else
   2607                     {
   2608                         /**< Loop on each output pixel in a row */
   2609                         for(k=0;k<pOut[i].u_width;k++)
   2610                         {
   2611 
   2612                             u32_y_frac = (u32_y_accum >> 12)&15; /* Vertical weight factor */
   2613 
   2614                             pu8_src_top = pu8_data_in + (pC->u32_x_accum[i] >> 16);
   2615 
   2616                             pu8_src_bottom = pu8_src_top + i32_tmp_offset;
   2617 
   2618                             /* Weighted combination */
   2619                             u32_temp_value = (M4VIFI_UInt8)(((pu8_src_top[0]*(16-u32_x_frac) +
   2620                                                                  pu8_src_top[1]*u32_x_frac)*(16-u32_y_frac) +
   2621                                                                 (pu8_src_bottom[0]*(16-u32_x_frac) +
   2622                                                                  pu8_src_bottom[1]*u32_x_frac)*u32_y_frac )>>8);
   2623 
   2624                             *pu8_data_out++ = (M4VIFI_UInt8)u32_temp_value;
   2625 
   2626                             /* Update vertical accumulator */
   2627                             u32_y_accum += pC->u32_y_inc[i];
   2628                             if (u32_y_accum>>16)
   2629                             {
   2630                                 pu8_data_in = pu8_data_in + (u32_y_accum >> 16) * i32_tmp_offset;
   2631                                 u32_y_accum &= 0xffff;
   2632                             }
   2633                         }
   2634                     }
   2635                     pu8_data_out += pOut[i].u_stride - pOut[i].u_width;
   2636 
   2637                     /* Update horizontal accumulator */
   2638                     pC->u32_x_accum[i] += pC->u32_x_inc[i];
   2639 
   2640                     pu8_data_in = pu8_data_in_org;
   2641                 }
   2642 
   2643             }
   2644             }/** 3 != i */
   2645             else
   2646             {
   2647             /**No +-90 rotation */
   2648             if(M4OSA_FALSE == pC->m_bRevertXY)
   2649             {
   2650 
   2651                 /**< Loop on each row */
   2652                 for(j=0;j<pOut[i].u_height;j++)
   2653                 {
   2654                     /* Vertical weight factor */
   2655                     u32_y_frac = (pC->u32_y_accum[i]>>12)&15;
   2656 
   2657                     /* Reinit horizontal weight factor */
   2658                     u32_x_accum = pC->u32_x_accum_start[i];
   2659 
   2660 
   2661 
   2662                         if(M4OSA_TRUE ==  pC->m_bFlipX)
   2663                         {
   2664 
   2665                             /**< Loop on each output pixel in a row */
   2666                             for(k=0;k<pOut[i].u_width;k++)
   2667                             {
   2668 
   2669                                 u32_x_frac = (u32_x_accum >> 12)&15; /* Fraction of Horizontal weight factor */
   2670 
   2671                                 pu8_src_top = (pu8_data_in - (u32_x_accum >> 16)) -1 ;
   2672 
   2673                                 pu8_src_bottom = pu8_src_top + i32_tmp_offset;
   2674 
   2675                                 /* Weighted combination */
   2676                                 u32_temp_value = (M4VIFI_UInt8)(((pu8_src_top[1]*(16-u32_x_frac) +
   2677                                                                  pu8_src_top[0]*u32_x_frac)*(16-u32_y_frac) +
   2678                                                                 (pu8_src_bottom[1]*(16-u32_x_frac) +
   2679                                                                  pu8_src_bottom[0]*u32_x_frac)*u32_y_frac )>>8);
   2680 
   2681                                 u32_temp_value= (u32_temp_value >> 7)*0xff;
   2682 
   2683                                 *pu8_data_out++ = (M4VIFI_UInt8)u32_temp_value;
   2684 
   2685                                 /* Update horizontal accumulator */
   2686                                 u32_x_accum += pC->u32_x_inc[i];
   2687                             }
   2688                         }
   2689 
   2690                         else
   2691                         {
   2692                             /**< Loop on each output pixel in a row */
   2693                             for(k=0;k<pOut[i].u_width;k++)
   2694                             {
   2695                                 u32_x_frac = (u32_x_accum >> 12)&15; /* Fraction of Horizontal weight factor */
   2696 
   2697                                 pu8_src_top = pu8_data_in + (u32_x_accum >> 16);
   2698 
   2699                                 pu8_src_bottom = pu8_src_top + i32_tmp_offset;
   2700 
   2701                                 /* Weighted combination */
   2702                                 u32_temp_value = (M4VIFI_UInt8)(((pu8_src_top[0]*(16-u32_x_frac) +
   2703                                                                  pu8_src_top[1]*u32_x_frac)*(16-u32_y_frac) +
   2704                                                                 (pu8_src_bottom[0]*(16-u32_x_frac) +
   2705                                                                  pu8_src_bottom[1]*u32_x_frac)*u32_y_frac )>>8);
   2706 
   2707                                 u32_temp_value= (u32_temp_value >> 7)*0xff;
   2708 
   2709                                 *pu8_data_out++ = (M4VIFI_UInt8)u32_temp_value;
   2710 
   2711                                 /* Update horizontal accumulator */
   2712                                 u32_x_accum += pC->u32_x_inc[i];
   2713                             }
   2714 
   2715                         }
   2716 
   2717                     pu8_data_out += pOut[i].u_stride - pOut[i].u_width;
   2718 
   2719                     /* Update vertical accumulator */
   2720                     pC->u32_y_accum[i] += pC->u32_y_inc[i];
   2721                     if (pC->u32_y_accum[i]>>16)
   2722                     {
   2723                         pu8_data_in = pu8_data_in + (pC->u32_y_accum[i] >> 16) * i32_tmp_offset;
   2724                         pC->u32_y_accum[i] &= 0xffff;
   2725                     }
   2726                 }
   2727 
   2728             } /**< M4OSA_FALSE == pC->m_bRevertXY */
   2729             /** +-90 rotation */
   2730             else
   2731             {
   2732                 pu8_data_in_org = pu8_data_in;
   2733 
   2734                 /**< Loop on each output row */
   2735                 for(j=0;j<pOut[i].u_height;j++)
   2736                 {
   2737                     /* horizontal weight factor */
   2738                     u32_x_frac = (pC->u32_x_accum[i]>>12)&15;
   2739 
   2740                     /* Reinit accumulator */
   2741                     u32_y_accum = pC->u32_y_accum_start[i];
   2742 
   2743                     if(M4OSA_TRUE ==  pC->m_bFlipX)
   2744                     {
   2745 
   2746                         /**< Loop on each output pixel in a row */
   2747                         for(k=0;k<pOut[i].u_width;k++)
   2748                         {
   2749 
   2750                             u32_y_frac = (u32_y_accum >> 12)&15; /* Vertical weight factor */
   2751 
   2752 
   2753                             pu8_src_top = (pu8_data_in - (pC->u32_x_accum[i] >> 16)) - 1;
   2754 
   2755                             pu8_src_bottom = pu8_src_top + i32_tmp_offset;
   2756 
   2757                             /* Weighted combination */
   2758                             u32_temp_value = (M4VIFI_UInt8)(((pu8_src_top[1]*(16-u32_x_frac) +
   2759                                                                  pu8_src_top[0]*u32_x_frac)*(16-u32_y_frac) +
   2760                                                                 (pu8_src_bottom[1]*(16-u32_x_frac) +
   2761                                                                  pu8_src_bottom[0]*u32_x_frac)*u32_y_frac )>>8);
   2762 
   2763                             u32_temp_value= (u32_temp_value >> 7)*0xff;
   2764 
   2765                             *pu8_data_out++ = (M4VIFI_UInt8)u32_temp_value;
   2766 
   2767                             /* Update vertical accumulator */
   2768                             u32_y_accum += pC->u32_y_inc[i];
   2769                             if (u32_y_accum>>16)
   2770                             {
   2771                                 pu8_data_in = pu8_data_in + (u32_y_accum >> 16) * i32_tmp_offset;
   2772                                 u32_y_accum &= 0xffff;
   2773                             }
   2774 
   2775                         }
   2776                     }
   2777                     else
   2778                     {
   2779                         /**< Loop on each output pixel in a row */
   2780                         for(k=0;k<pOut[i].u_width;k++)
   2781                         {
   2782 
   2783                             u32_y_frac = (u32_y_accum >> 12)&15; /* Vertical weight factor */
   2784 
   2785                             pu8_src_top = pu8_data_in + (pC->u32_x_accum[i] >> 16);
   2786 
   2787                             pu8_src_bottom = pu8_src_top + i32_tmp_offset;
   2788 
   2789                             /* Weighted combination */
   2790                             u32_temp_value = (M4VIFI_UInt8)(((pu8_src_top[0]*(16-u32_x_frac) +
   2791                                                                  pu8_src_top[1]*u32_x_frac)*(16-u32_y_frac) +
   2792                                                                 (pu8_src_bottom[0]*(16-u32_x_frac) +
   2793                                                                  pu8_src_bottom[1]*u32_x_frac)*u32_y_frac )>>8);
   2794 
   2795                             u32_temp_value= (u32_temp_value >> 7)*0xff;
   2796 
   2797                             *pu8_data_out++ = (M4VIFI_UInt8)u32_temp_value;
   2798 
   2799                             /* Update vertical accumulator */
   2800                             u32_y_accum += pC->u32_y_inc[i];
   2801                             if (u32_y_accum>>16)
   2802                             {
   2803                                 pu8_data_in = pu8_data_in + (u32_y_accum >> 16) * i32_tmp_offset;
   2804                                 u32_y_accum &= 0xffff;
   2805                             }
   2806                         }
   2807                     }
   2808                     pu8_data_out += pOut[i].u_stride - pOut[i].u_width;
   2809 
   2810                     /* Update horizontal accumulator */
   2811                     pC->u32_x_accum[i] += pC->u32_x_inc[i];
   2812 
   2813                     pu8_data_in = pu8_data_in_org;
   2814 
   2815                 }
   2816                 } /**< M4OSA_TRUE == pC->m_bRevertXY */
   2817         }/** 3 == i */
   2818             }
   2819         /**< In case of stripe mode, save current input pointer */
   2820         if(M4OSA_TRUE == pC->m_params.m_bOutputStripe)
   2821         {
   2822             pC->pu8_data_in[i] = pu8_data_in;
   2823         }
   2824     }
   2825 
   2826     /**< Update number of processed rows, reset it if we have finished with the whole processing */
   2827     pC->m_procRows += pOut[0].u_height;
   2828     if(M4OSA_FALSE == pC->m_bRevertXY)
   2829     {
   2830         if(pC->m_params.m_outputSize.m_height <= pC->m_procRows)    pC->m_procRows = 0;
   2831     }
   2832     else
   2833     {
   2834         if(pC->m_params.m_outputSize.m_width <= pC->m_procRows) pC->m_procRows = 0;
   2835     }
   2836 
   2837     return M4NO_ERROR ;
   2838 
   2839 }
   2840 /*+ Handle the image files here */
   2841 
   2842 /**
   2843  ******************************************************************************
   2844  * M4OSA_ERR LvGetImageThumbNail(M4OSA_UChar *fileName, M4OSA_Void **pBuffer)
   2845  * @brief   This function gives YUV420 buffer of a given image file (in argb888 format)
   2846  * @Note: The caller of the function is responsible to free the yuv buffer allocated
   2847  * @param   fileName:       (IN) Path to the filename of the image argb data
   2848  * @param   height:     (IN) Height of the image
   2849  * @param     width:             (OUT) pBuffer pointer to the address where the yuv data address needs to be returned.
   2850  * @return  M4NO_ERROR: there is no error
   2851  * @return  M4ERR_ALLOC: No more memory space to add a new effect.
   2852  * @return  M4ERR_FILE_NOT_FOUND: if the file passed does not exists.
   2853  ******************************************************************************
   2854 */
   2855 M4OSA_ERR LvGetImageThumbNail(const char *fileName, M4OSA_UInt32 height, M4OSA_UInt32 width, M4OSA_Void **pBuffer) {
   2856 
   2857     M4VIFI_ImagePlane rgbPlane, *yuvPlane;
   2858     M4OSA_UInt32 frameSize_argb = (width * height * 4); // argb data
   2859     M4OSA_Context lImageFileFp  = M4OSA_NULL;
   2860     M4OSA_ERR err = M4NO_ERROR;
   2861 
   2862     M4OSA_UInt8 *pTmpData = (M4OSA_UInt8*) M4OSA_32bitAlignedMalloc(frameSize_argb, M4VS, (M4OSA_Char*)"Image argb data");
   2863     if(pTmpData == M4OSA_NULL) {
   2864         LOGE("Failed to allocate memory for Image clip");
   2865         return M4ERR_ALLOC;
   2866     }
   2867 
   2868        /** Read the argb data from the passed file. */
   2869     M4OSA_ERR lerr = M4OSA_fileReadOpen(&lImageFileFp, (M4OSA_Void *) fileName, M4OSA_kFileRead);
   2870 
   2871     if((lerr != M4NO_ERROR) || (lImageFileFp == M4OSA_NULL))
   2872     {
   2873         LOGE("LVPreviewController: Can not open the file ");
   2874         free(pTmpData);
   2875         return M4ERR_FILE_NOT_FOUND;
   2876     }
   2877     lerr = M4OSA_fileReadData(lImageFileFp, (M4OSA_MemAddr8)pTmpData, &frameSize_argb);
   2878     if(lerr != M4NO_ERROR)
   2879     {
   2880         LOGE("LVPreviewController: can not read the data ");
   2881         M4OSA_fileReadClose(lImageFileFp);
   2882         free(pTmpData);
   2883         return lerr;
   2884     }
   2885     M4OSA_fileReadClose(lImageFileFp);
   2886 
   2887     M4OSA_UInt32 frameSize = (width * height * 3); //Size of YUV420 data.
   2888     rgbPlane.pac_data = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc(frameSize, M4VS, (M4OSA_Char*)"Image clip RGB888 data");
   2889     if(rgbPlane.pac_data == M4OSA_NULL)
   2890     {
   2891         LOGE("Failed to allocate memory for Image clip");
   2892         free(pTmpData);
   2893         return M4ERR_ALLOC;
   2894     }
   2895 
   2896     /** Remove the alpha channel */
   2897     for (M4OSA_UInt32 i=0, j = 0; i < frameSize_argb; i++) {
   2898         if ((i % 4) == 0) continue;
   2899         rgbPlane.pac_data[j] = pTmpData[i];
   2900         j++;
   2901     }
   2902     free(pTmpData);
   2903 
   2904 #ifdef FILE_DUMP
   2905     FILE *fp = fopen("/sdcard/Input/test_rgb.raw", "wb");
   2906     if(fp == NULL)
   2907         LOGE("Errors file can not be created");
   2908     else {
   2909         fwrite(rgbPlane.pac_data, frameSize, 1, fp);
   2910         fclose(fp);
   2911     }
   2912 #endif
   2913         rgbPlane.u_height = height;
   2914         rgbPlane.u_width = width;
   2915         rgbPlane.u_stride = width*3;
   2916         rgbPlane.u_topleft = 0;
   2917 
   2918         yuvPlane = (M4VIFI_ImagePlane*)M4OSA_32bitAlignedMalloc(3*sizeof(M4VIFI_ImagePlane),
   2919                 M4VS, (M4OSA_Char*)"M4xVSS_internalConvertRGBtoYUV: Output plane YUV");
   2920         yuvPlane[0].u_height = height;
   2921         yuvPlane[0].u_width = width;
   2922         yuvPlane[0].u_stride = width;
   2923         yuvPlane[0].u_topleft = 0;
   2924         yuvPlane[0].pac_data = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc(yuvPlane[0].u_height * yuvPlane[0].u_width * 1.5, M4VS, (M4OSA_Char*)"imageClip YUV data");
   2925 
   2926         yuvPlane[1].u_height = yuvPlane[0].u_height >>1;
   2927         yuvPlane[1].u_width = yuvPlane[0].u_width >> 1;
   2928         yuvPlane[1].u_stride = yuvPlane[1].u_width;
   2929         yuvPlane[1].u_topleft = 0;
   2930         yuvPlane[1].pac_data = (M4VIFI_UInt8*)(yuvPlane[0].pac_data + yuvPlane[0].u_height * yuvPlane[0].u_width);
   2931 
   2932         yuvPlane[2].u_height = yuvPlane[0].u_height >>1;
   2933         yuvPlane[2].u_width = yuvPlane[0].u_width >> 1;
   2934         yuvPlane[2].u_stride = yuvPlane[2].u_width;
   2935         yuvPlane[2].u_topleft = 0;
   2936         yuvPlane[2].pac_data = (M4VIFI_UInt8*)(yuvPlane[1].pac_data + yuvPlane[1].u_height * yuvPlane[1].u_width);
   2937 
   2938 
   2939         err = M4VIFI_RGB888toYUV420(M4OSA_NULL, &rgbPlane, yuvPlane);
   2940         //err = M4VIFI_BGR888toYUV420(M4OSA_NULL, &rgbPlane, yuvPlane);
   2941         if(err != M4NO_ERROR)
   2942         {
   2943             LOGE("error when converting from RGB to YUV: 0x%x\n", (unsigned int)err);
   2944         }
   2945         free(rgbPlane.pac_data);
   2946 
   2947         //LOGE("RGB to YUV done");
   2948 #ifdef FILE_DUMP
   2949         FILE *fp1 = fopen("/sdcard/Input/test_yuv.raw", "wb");
   2950         if(fp1 == NULL)
   2951             LOGE("Errors file can not be created");
   2952         else {
   2953             fwrite(yuvPlane[0].pac_data, yuvPlane[0].u_height * yuvPlane[0].u_width * 1.5, 1, fp1);
   2954             fclose(fp1);
   2955         }
   2956 #endif
   2957         *pBuffer = yuvPlane[0].pac_data;
   2958         free(yuvPlane);
   2959         return M4NO_ERROR;
   2960 
   2961 }
   2962 M4OSA_Void prepareYUV420ImagePlane(M4VIFI_ImagePlane *plane,
   2963     M4OSA_UInt32 width, M4OSA_UInt32 height, M4VIFI_UInt8 *buffer,
   2964     M4OSA_UInt32 reportedWidth, M4OSA_UInt32 reportedHeight) {
   2965 
   2966     //Y plane
   2967     plane[0].u_width = width;
   2968     plane[0].u_height = height;
   2969     plane[0].u_stride = reportedWidth;
   2970     plane[0].u_topleft = 0;
   2971     plane[0].pac_data = buffer;
   2972 
   2973     // U plane
   2974     plane[1].u_width = width/2;
   2975     plane[1].u_height = height/2;
   2976     plane[1].u_stride = reportedWidth >> 1;
   2977     plane[1].u_topleft = 0;
   2978     plane[1].pac_data = buffer+(reportedWidth*reportedHeight);
   2979 
   2980     // V Plane
   2981     plane[2].u_width = width/2;
   2982     plane[2].u_height = height/2;
   2983     plane[2].u_stride = reportedWidth >> 1;
   2984     plane[2].u_topleft = 0;
   2985     plane[2].pac_data = plane[1].pac_data + ((reportedWidth/2)*(reportedHeight/2));
   2986 }
   2987 
   2988 M4OSA_Void prepareYV12ImagePlane(M4VIFI_ImagePlane *plane,
   2989     M4OSA_UInt32 width, M4OSA_UInt32 height, M4OSA_UInt32 stride,
   2990     M4VIFI_UInt8 *buffer) {
   2991 
   2992     //Y plane
   2993     plane[0].u_width = width;
   2994     plane[0].u_height = height;
   2995     plane[0].u_stride = stride;
   2996     plane[0].u_topleft = 0;
   2997     plane[0].pac_data = buffer;
   2998 
   2999     // U plane
   3000     plane[1].u_width = width/2;
   3001     plane[1].u_height = height/2;
   3002     plane[1].u_stride = android::PreviewRenderer::ALIGN(plane[0].u_stride/2, 16);
   3003     plane[1].u_topleft = 0;
   3004     plane[1].pac_data = (buffer
   3005                 + plane[0].u_height * plane[0].u_stride
   3006                 + (plane[0].u_height/2) * android::PreviewRenderer::ALIGN((
   3007                  plane[0].u_stride / 2), 16));
   3008 
   3009     // V Plane
   3010     plane[2].u_width = width/2;
   3011     plane[2].u_height = height/2;
   3012     plane[2].u_stride = android::PreviewRenderer::ALIGN(plane[0].u_stride/2, 16);
   3013     plane[2].u_topleft = 0;
   3014     plane[2].pac_data = (buffer +
   3015      plane[0].u_height * android::PreviewRenderer::ALIGN(plane[0].u_stride, 16));
   3016 
   3017 
   3018 }
   3019 
   3020 M4OSA_Void swapImagePlanes(
   3021     M4VIFI_ImagePlane *planeIn, M4VIFI_ImagePlane *planeOut,
   3022     M4VIFI_UInt8 *buffer1, M4VIFI_UInt8 *buffer2) {
   3023 
   3024     planeIn[0].u_height = planeOut[0].u_height;
   3025     planeIn[0].u_width = planeOut[0].u_width;
   3026     planeIn[0].u_stride = planeOut[0].u_stride;
   3027     planeIn[0].u_topleft = planeOut[0].u_topleft;
   3028     planeIn[0].pac_data = planeOut[0].pac_data;
   3029 
   3030     /**
   3031      * U plane */
   3032     planeIn[1].u_width = planeOut[1].u_width;
   3033     planeIn[1].u_height = planeOut[1].u_height;
   3034     planeIn[1].u_stride = planeOut[1].u_stride;
   3035     planeIn[1].u_topleft = planeOut[1].u_topleft;
   3036     planeIn[1].pac_data = planeOut[1].pac_data;
   3037     /**
   3038      * V Plane */
   3039     planeIn[2].u_width = planeOut[2].u_width;
   3040     planeIn[2].u_height = planeOut[2].u_height;
   3041     planeIn[2].u_stride = planeOut[2].u_stride;
   3042     planeIn[2].u_topleft = planeOut[2].u_topleft;
   3043     planeIn[2].pac_data = planeOut[2].pac_data;
   3044 
   3045     if(planeOut[0].pac_data == (M4VIFI_UInt8*)buffer1)
   3046     {
   3047         planeOut[0].pac_data = (M4VIFI_UInt8*)buffer2;
   3048         planeOut[1].pac_data = (M4VIFI_UInt8*)(buffer2 +
   3049          planeOut[0].u_width*planeOut[0].u_height);
   3050 
   3051         planeOut[2].pac_data = (M4VIFI_UInt8*)(buffer2 +
   3052          planeOut[0].u_width*planeOut[0].u_height +
   3053          planeOut[1].u_width*planeOut[1].u_height);
   3054     }
   3055     else
   3056     {
   3057         planeOut[0].pac_data = (M4VIFI_UInt8*)buffer1;
   3058         planeOut[1].pac_data = (M4VIFI_UInt8*)(buffer1 +
   3059          planeOut[0].u_width*planeOut[0].u_height);
   3060 
   3061         planeOut[2].pac_data = (M4VIFI_UInt8*)(buffer1 +
   3062          planeOut[0].u_width*planeOut[0].u_height +
   3063          planeOut[1].u_width*planeOut[1].u_height);
   3064     }
   3065 
   3066 }
   3067 
   3068 M4OSA_Void computePercentageDone(
   3069     M4OSA_UInt32 ctsMs, M4OSA_UInt32 effectStartTimeMs,
   3070     M4OSA_UInt32 effectDuration, M4OSA_Double *percentageDone) {
   3071 
   3072     M4OSA_Double videoEffectTime =0;
   3073 
   3074     // Compute how far from the beginning of the effect we are, in clip-base time.
   3075     videoEffectTime =
   3076      (M4OSA_Int32)(ctsMs+ 0.5) - effectStartTimeMs;
   3077 
   3078     // To calculate %, substract timeIncrement
   3079     // because effect should finish on the last frame
   3080     // which is from CTS = (eof-timeIncrement) till CTS = eof
   3081     *percentageDone =
   3082      videoEffectTime / ((M4OSA_Float)effectDuration);
   3083 
   3084     if(*percentageDone < 0.0) *percentageDone = 0.0;
   3085     if(*percentageDone > 1.0) *percentageDone = 1.0;
   3086 
   3087 }
   3088 
   3089 
   3090 M4OSA_Void computeProgressForVideoEffect(
   3091     M4OSA_UInt32 ctsMs, M4OSA_UInt32 effectStartTimeMs,
   3092     M4OSA_UInt32 effectDuration, M4VSS3GPP_ExternalProgress* extProgress) {
   3093 
   3094     M4OSA_Double percentageDone =0;
   3095 
   3096     computePercentageDone(ctsMs, effectStartTimeMs, effectDuration, &percentageDone);
   3097 
   3098     extProgress->uiProgress = (M4OSA_UInt32)( percentageDone * 1000 );
   3099     extProgress->uiOutputTime = (M4OSA_UInt32)(ctsMs + 0.5);
   3100     extProgress->uiClipTime = extProgress->uiOutputTime;
   3101     extProgress->bIsLast = M4OSA_FALSE;
   3102 }
   3103 
   3104 M4OSA_ERR prepareFramingStructure(
   3105     M4xVSS_FramingStruct* framingCtx,
   3106     M4VSS3GPP_EffectSettings* effectsSettings, M4OSA_UInt32 index,
   3107     M4VIFI_UInt8* overlayRGB, M4VIFI_UInt8* overlayYUV) {
   3108 
   3109     M4OSA_ERR err = M4NO_ERROR;
   3110 
   3111     // Force input RGB buffer to even size to avoid errors in YUV conversion
   3112     framingCtx->FramingRgb = effectsSettings[index].xVSS.pFramingBuffer;
   3113     framingCtx->FramingRgb->u_width = framingCtx->FramingRgb->u_width & ~1;
   3114     framingCtx->FramingRgb->u_height = framingCtx->FramingRgb->u_height & ~1;
   3115     framingCtx->FramingYuv = NULL;
   3116 
   3117     framingCtx->duration = effectsSettings[index].uiDuration;
   3118     framingCtx->topleft_x = effectsSettings[index].xVSS.topleft_x;
   3119     framingCtx->topleft_y = effectsSettings[index].xVSS.topleft_y;
   3120     framingCtx->pCurrent = framingCtx;
   3121     framingCtx->pNext = framingCtx;
   3122     framingCtx->previousClipTime = -1;
   3123 
   3124     framingCtx->alphaBlendingStruct =
   3125      (M4xVSS_internalEffectsAlphaBlending*)M4OSA_32bitAlignedMalloc(
   3126       sizeof(M4xVSS_internalEffectsAlphaBlending), M4VS,
   3127       (M4OSA_Char*)"alpha blending struct");
   3128 
   3129     framingCtx->alphaBlendingStruct->m_fadeInTime =
   3130      effectsSettings[index].xVSS.uialphaBlendingFadeInTime;
   3131 
   3132     framingCtx->alphaBlendingStruct->m_fadeOutTime =
   3133      effectsSettings[index].xVSS.uialphaBlendingFadeOutTime;
   3134 
   3135     framingCtx->alphaBlendingStruct->m_end =
   3136      effectsSettings[index].xVSS.uialphaBlendingEnd;
   3137 
   3138     framingCtx->alphaBlendingStruct->m_middle =
   3139      effectsSettings[index].xVSS.uialphaBlendingMiddle;
   3140 
   3141     framingCtx->alphaBlendingStruct->m_start =
   3142      effectsSettings[index].xVSS.uialphaBlendingStart;
   3143 
   3144     // If new Overlay buffer, convert from RGB to YUV
   3145     if((overlayRGB != framingCtx->FramingRgb->pac_data) || (overlayYUV == NULL) ) {
   3146 
   3147         // If YUV buffer exists, delete it
   3148         if(overlayYUV != NULL) {
   3149            free(overlayYUV);
   3150            overlayYUV = NULL;
   3151         }
   3152     if(effectsSettings[index].xVSS.rgbType == M4VSS3GPP_kRGB565) {
   3153         // Input RGB565 plane is provided,
   3154         // let's convert it to YUV420, and update framing structure
   3155         err = M4xVSS_internalConvertRGBtoYUV(framingCtx);
   3156     }
   3157     else if(effectsSettings[index].xVSS.rgbType == M4VSS3GPP_kRGB888) {
   3158         // Input RGB888 plane is provided,
   3159         // let's convert it to YUV420, and update framing structure
   3160         err = M4xVSS_internalConvertRGB888toYUV(framingCtx);
   3161     }
   3162     else {
   3163         err = M4ERR_PARAMETER;
   3164     }
   3165         overlayYUV = framingCtx->FramingYuv[0].pac_data;
   3166         overlayRGB = framingCtx->FramingRgb->pac_data;
   3167 
   3168     }
   3169     else {
   3170         LOGV(" YUV buffer reuse");
   3171         framingCtx->FramingYuv = (M4VIFI_ImagePlane*)M4OSA_32bitAlignedMalloc(
   3172             3*sizeof(M4VIFI_ImagePlane), M4VS, (M4OSA_Char*)"YUV");
   3173 
   3174         if(framingCtx->FramingYuv == M4OSA_NULL) {
   3175             return M4ERR_ALLOC;
   3176         }
   3177 
   3178         framingCtx->FramingYuv[0].u_width = framingCtx->FramingRgb->u_width;
   3179         framingCtx->FramingYuv[0].u_height = framingCtx->FramingRgb->u_height;
   3180         framingCtx->FramingYuv[0].u_topleft = 0;
   3181         framingCtx->FramingYuv[0].u_stride = framingCtx->FramingRgb->u_width;
   3182         framingCtx->FramingYuv[0].pac_data = (M4VIFI_UInt8*)overlayYUV;
   3183 
   3184         framingCtx->FramingYuv[1].u_width = (framingCtx->FramingRgb->u_width)>>1;
   3185         framingCtx->FramingYuv[1].u_height = (framingCtx->FramingRgb->u_height)>>1;
   3186         framingCtx->FramingYuv[1].u_topleft = 0;
   3187         framingCtx->FramingYuv[1].u_stride = (framingCtx->FramingRgb->u_width)>>1;
   3188         framingCtx->FramingYuv[1].pac_data = framingCtx->FramingYuv[0].pac_data +
   3189             framingCtx->FramingYuv[0].u_width * framingCtx->FramingYuv[0].u_height;
   3190 
   3191         framingCtx->FramingYuv[2].u_width = (framingCtx->FramingRgb->u_width)>>1;
   3192         framingCtx->FramingYuv[2].u_height = (framingCtx->FramingRgb->u_height)>>1;
   3193         framingCtx->FramingYuv[2].u_topleft = 0;
   3194         framingCtx->FramingYuv[2].u_stride = (framingCtx->FramingRgb->u_width)>>1;
   3195         framingCtx->FramingYuv[2].pac_data = framingCtx->FramingYuv[1].pac_data +
   3196             framingCtx->FramingYuv[1].u_width * framingCtx->FramingYuv[1].u_height;
   3197 
   3198         framingCtx->duration = 0;
   3199         framingCtx->previousClipTime = -1;
   3200         framingCtx->previewOffsetClipTime = -1;
   3201 
   3202     }
   3203     return err;
   3204 }
   3205 
   3206 M4OSA_ERR applyColorEffect(M4xVSS_VideoEffectType colorEffect,
   3207     M4VIFI_ImagePlane *planeIn, M4VIFI_ImagePlane *planeOut,
   3208     M4VIFI_UInt8 *buffer1, M4VIFI_UInt8 *buffer2, M4OSA_UInt16 rgbColorData) {
   3209 
   3210     M4xVSS_ColorStruct colorContext;
   3211     M4OSA_ERR err = M4NO_ERROR;
   3212 
   3213     colorContext.colorEffectType = colorEffect;
   3214     colorContext.rgb16ColorData = rgbColorData;
   3215 
   3216     err = M4VSS3GPP_externalVideoEffectColor(
   3217      (M4OSA_Void *)&colorContext, planeIn, planeOut, NULL,
   3218      colorEffect);
   3219 
   3220     if(err != M4NO_ERROR) {
   3221         LOGV("M4VSS3GPP_externalVideoEffectColor(%d) error %d",
   3222             colorEffect, err);
   3223 
   3224         if(NULL != buffer1) {
   3225             free(buffer1);
   3226             buffer1 = NULL;
   3227         }
   3228         if(NULL != buffer2) {
   3229             free(buffer2);
   3230             buffer2 = NULL;
   3231         }
   3232         return err;
   3233     }
   3234 
   3235     // The out plane now becomes the in plane for adding other effects
   3236     swapImagePlanes(planeIn, planeOut, buffer1, buffer2);
   3237 
   3238     return err;
   3239 }
   3240 
   3241 M4OSA_ERR applyLumaEffect(M4VSS3GPP_VideoEffectType videoEffect,
   3242     M4VIFI_ImagePlane *planeIn, M4VIFI_ImagePlane *planeOut,
   3243     M4VIFI_UInt8 *buffer1, M4VIFI_UInt8 *buffer2, M4OSA_Int32 lum_factor) {
   3244 
   3245     M4OSA_ERR err = M4NO_ERROR;
   3246 
   3247     err = M4VFL_modifyLumaWithScale(
   3248          (M4ViComImagePlane*)planeIn,(M4ViComImagePlane*)planeOut,
   3249          lum_factor, NULL);
   3250 
   3251     if(err != M4NO_ERROR) {
   3252         LOGE("M4VFL_modifyLumaWithScale(%d) error %d", videoEffect, (int)err);
   3253 
   3254         if(NULL != buffer1) {
   3255             free(buffer1);
   3256             buffer1= NULL;
   3257         }
   3258         if(NULL != buffer2) {
   3259             free(buffer2);
   3260             buffer2= NULL;
   3261         }
   3262         return err;
   3263     }
   3264 
   3265     // The out plane now becomes the in plane for adding other effects
   3266     swapImagePlanes(planeIn, planeOut,(M4VIFI_UInt8 *)buffer1,
   3267      (M4VIFI_UInt8 *)buffer2);
   3268 
   3269     return err;
   3270 }
   3271 
   3272 M4OSA_ERR applyEffectsAndRenderingMode(vePostProcessParams *params,
   3273     M4OSA_UInt32 reportedWidth, M4OSA_UInt32 reportedHeight) {
   3274 
   3275     M4OSA_ERR err = M4NO_ERROR;
   3276     M4VIFI_ImagePlane planeIn[3], planeOut[3];
   3277     M4VIFI_UInt8 *finalOutputBuffer = NULL, *tempOutputBuffer= NULL;
   3278     M4OSA_Double percentageDone =0;
   3279     M4OSA_Int32 lum_factor;
   3280     M4VSS3GPP_ExternalProgress extProgress;
   3281     M4xVSS_FiftiesStruct fiftiesCtx;
   3282     M4OSA_UInt32 frameSize = 0, i=0;
   3283 
   3284     frameSize = (params->videoWidth*params->videoHeight*3) >> 1;
   3285 
   3286     finalOutputBuffer = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc(frameSize, M4VS,
   3287      (M4OSA_Char*)("lvpp finalOutputBuffer"));
   3288 
   3289     if(finalOutputBuffer == NULL) {
   3290         LOGE("applyEffectsAndRenderingMode: malloc error");
   3291         return M4ERR_ALLOC;
   3292     }
   3293 
   3294     // allocate the tempOutputBuffer
   3295     tempOutputBuffer = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc(
   3296      ((params->videoHeight*params->videoWidth*3)>>1), M4VS, (M4OSA_Char*)("lvpp colorBuffer"));
   3297 
   3298     if(tempOutputBuffer == NULL) {
   3299         LOGE("applyEffectsAndRenderingMode: malloc error tempOutputBuffer");
   3300         if(NULL != finalOutputBuffer) {
   3301             free(finalOutputBuffer);
   3302             finalOutputBuffer = NULL;
   3303         }
   3304         return M4ERR_ALLOC;
   3305     }
   3306 
   3307     // Initialize the In plane
   3308     prepareYUV420ImagePlane(planeIn, params->videoWidth, params->videoHeight,
   3309        params->vidBuffer, reportedWidth, reportedHeight);
   3310 
   3311     // Initialize the Out plane
   3312     prepareYUV420ImagePlane(planeOut, params->videoWidth, params->videoHeight,
   3313        (M4VIFI_UInt8 *)tempOutputBuffer, params->videoWidth, params->videoHeight);
   3314 
   3315     // The planeIn contains the YUV420 input data to postprocessing node
   3316     // and planeOut will contain the YUV420 data with effect
   3317     // In each successive if condition, apply filter to successive
   3318     // output YUV frame so that concurrent effects are both applied
   3319 
   3320     if(params->currentVideoEffect & VIDEO_EFFECT_BLACKANDWHITE) {
   3321         err = applyColorEffect(M4xVSS_kVideoEffectType_BlackAndWhite,
   3322               planeIn, planeOut, (M4VIFI_UInt8 *)finalOutputBuffer,
   3323               (M4VIFI_UInt8 *)tempOutputBuffer, 0);
   3324         if(err != M4NO_ERROR) {
   3325             return err;
   3326         }
   3327     }
   3328 
   3329     if(params->currentVideoEffect & VIDEO_EFFECT_PINK) {
   3330         err = applyColorEffect(M4xVSS_kVideoEffectType_Pink,
   3331               planeIn, planeOut, (M4VIFI_UInt8 *)finalOutputBuffer,
   3332               (M4VIFI_UInt8 *)tempOutputBuffer, 0);
   3333         if(err != M4NO_ERROR) {
   3334             return err;
   3335         }
   3336     }
   3337 
   3338     if(params->currentVideoEffect & VIDEO_EFFECT_GREEN) {
   3339         err = applyColorEffect(M4xVSS_kVideoEffectType_Green,
   3340               planeIn, planeOut, (M4VIFI_UInt8 *)finalOutputBuffer,
   3341               (M4VIFI_UInt8 *)tempOutputBuffer, 0);
   3342         if(err != M4NO_ERROR) {
   3343             return err;
   3344         }
   3345     }
   3346 
   3347     if(params->currentVideoEffect & VIDEO_EFFECT_SEPIA) {
   3348         err = applyColorEffect(M4xVSS_kVideoEffectType_Sepia,
   3349               planeIn, planeOut, (M4VIFI_UInt8 *)finalOutputBuffer,
   3350               (M4VIFI_UInt8 *)tempOutputBuffer, 0);
   3351         if(err != M4NO_ERROR) {
   3352             return err;
   3353         }
   3354     }
   3355 
   3356     if(params->currentVideoEffect & VIDEO_EFFECT_NEGATIVE) {
   3357         err = applyColorEffect(M4xVSS_kVideoEffectType_Negative,
   3358               planeIn, planeOut, (M4VIFI_UInt8 *)finalOutputBuffer,
   3359               (M4VIFI_UInt8 *)tempOutputBuffer, 0);
   3360         if(err != M4NO_ERROR) {
   3361             return err;
   3362         }
   3363     }
   3364 
   3365     if(params->currentVideoEffect & VIDEO_EFFECT_GRADIENT) {
   3366         // find the effect in effectSettings array
   3367         for(i=0;i<params->numberEffects;i++) {
   3368             if(params->effectsSettings[i].VideoEffectType ==
   3369              (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Gradient)
   3370                 break;
   3371         }
   3372         err = applyColorEffect(M4xVSS_kVideoEffectType_Gradient,
   3373               planeIn, planeOut, (M4VIFI_UInt8 *)finalOutputBuffer,
   3374               (M4VIFI_UInt8 *)tempOutputBuffer,
   3375               params->effectsSettings[i].xVSS.uiRgb16InputColor);
   3376         if(err != M4NO_ERROR) {
   3377             return err;
   3378         }
   3379     }
   3380 
   3381     if(params->currentVideoEffect & VIDEO_EFFECT_COLOR_RGB16) {
   3382         // Find the effect in effectSettings array
   3383         for(i=0;i<params->numberEffects;i++) {
   3384             if(params->effectsSettings[i].VideoEffectType ==
   3385              (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_ColorRGB16)
   3386                 break;
   3387         }
   3388         err = applyColorEffect(M4xVSS_kVideoEffectType_ColorRGB16,
   3389               planeIn, planeOut, (M4VIFI_UInt8 *)finalOutputBuffer,
   3390               (M4VIFI_UInt8 *)tempOutputBuffer,
   3391               params->effectsSettings[i].xVSS.uiRgb16InputColor);
   3392         if(err != M4NO_ERROR) {
   3393             return err;
   3394         }
   3395     }
   3396 
   3397     if(params->currentVideoEffect & VIDEO_EFFECT_FIFTIES) {
   3398         // Find the effect in effectSettings array
   3399         for(i=0;i<params->numberEffects;i++) {
   3400             if(params->effectsSettings[i].VideoEffectType ==
   3401              (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Fifties)
   3402                 break;
   3403         }
   3404         if(i < params->numberEffects) {
   3405             computeProgressForVideoEffect(params->timeMs,
   3406              params->effectsSettings[i].uiStartTime,
   3407              params->effectsSettings[i].uiDuration, &extProgress);
   3408 
   3409             if(params->isFiftiesEffectStarted) {
   3410                 fiftiesCtx.previousClipTime = -1;
   3411             }
   3412             fiftiesCtx.fiftiesEffectDuration =
   3413              1000/params->effectsSettings[i].xVSS.uiFiftiesOutFrameRate;
   3414 
   3415             fiftiesCtx.shiftRandomValue = 0;
   3416             fiftiesCtx.stripeRandomValue = 0;
   3417 
   3418             err = M4VSS3GPP_externalVideoEffectFifties(
   3419              (M4OSA_Void *)&fiftiesCtx, planeIn, planeOut, &extProgress,
   3420              M4xVSS_kVideoEffectType_Fifties);
   3421 
   3422             if(err != M4NO_ERROR) {
   3423                 LOGE("M4VSS3GPP_externalVideoEffectFifties error 0x%x", (unsigned int)err);
   3424 
   3425                 if(NULL != finalOutputBuffer) {
   3426                     free(finalOutputBuffer);
   3427                     finalOutputBuffer = NULL;
   3428                 }
   3429                 if(NULL != tempOutputBuffer) {
   3430                     free(tempOutputBuffer);
   3431                     tempOutputBuffer = NULL;
   3432                 }
   3433                 return err;
   3434             }
   3435 
   3436             // The out plane now becomes the in plane for adding other effects
   3437             swapImagePlanes(planeIn, planeOut,(M4VIFI_UInt8 *)finalOutputBuffer,
   3438              (M4VIFI_UInt8 *)tempOutputBuffer);
   3439         }
   3440     }
   3441 
   3442     if(params->currentVideoEffect & VIDEO_EFFECT_FRAMING) {
   3443 
   3444         M4xVSS_FramingStruct framingCtx;
   3445         // Find the effect in effectSettings array
   3446         for(i=0;i<params->numberEffects;i++) {
   3447             if(params->effectsSettings[i].VideoEffectType ==
   3448              (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) {
   3449                 if((params->effectsSettings[i].uiStartTime <= params->timeMs + params->timeOffset) &&
   3450                    ((params->effectsSettings[i].uiStartTime+
   3451                      params->effectsSettings[i].uiDuration) >= params->timeMs + params->timeOffset))
   3452                 {
   3453                         break;
   3454                 }
   3455             }
   3456         }
   3457         if(i < params->numberEffects) {
   3458             computeProgressForVideoEffect(params->timeMs,
   3459              params->effectsSettings[i].uiStartTime,
   3460              params->effectsSettings[i].uiDuration, &extProgress);
   3461 
   3462             err = prepareFramingStructure(&framingCtx,
   3463                   params->effectsSettings, i, params->overlayFrameRGBBuffer,
   3464                   params->overlayFrameYUVBuffer);
   3465 
   3466             if(err == M4NO_ERROR) {
   3467                 err = M4VSS3GPP_externalVideoEffectFraming(
   3468                       (M4OSA_Void *)&framingCtx, planeIn, planeOut, &extProgress,
   3469                       M4xVSS_kVideoEffectType_Framing);
   3470             }
   3471 
   3472             free(framingCtx.alphaBlendingStruct);
   3473 
   3474             if(framingCtx.FramingYuv != NULL) {
   3475                 free(framingCtx.FramingYuv);
   3476                 framingCtx.FramingYuv = NULL;
   3477             }
   3478             //If prepareFramingStructure / M4VSS3GPP_externalVideoEffectFraming
   3479             // returned error, then return from function
   3480             if(err != M4NO_ERROR) {
   3481 
   3482                 if(NULL != finalOutputBuffer) {
   3483                     free(finalOutputBuffer);
   3484                     finalOutputBuffer = NULL;
   3485                 }
   3486                 if(NULL != tempOutputBuffer) {
   3487                     free(tempOutputBuffer);
   3488                     tempOutputBuffer = NULL;
   3489                 }
   3490                 return err;
   3491             }
   3492 
   3493             // The out plane now becomes the in plane for adding other effects
   3494             swapImagePlanes(planeIn, planeOut,(M4VIFI_UInt8 *)finalOutputBuffer,
   3495              (M4VIFI_UInt8 *)tempOutputBuffer);
   3496         }
   3497     }
   3498 
   3499     if(params->currentVideoEffect & VIDEO_EFFECT_FADEFROMBLACK) {
   3500         /* find the effect in effectSettings array*/
   3501         for(i=0;i<params->numberEffects;i++) {
   3502             if(params->effectsSettings[i].VideoEffectType ==
   3503              M4VSS3GPP_kVideoEffectType_FadeFromBlack)
   3504                 break;
   3505         }
   3506 
   3507         if(i < params->numberEffects) {
   3508             computePercentageDone(params->timeMs,
   3509              params->effectsSettings[i].uiStartTime,
   3510              params->effectsSettings[i].uiDuration, &percentageDone);
   3511 
   3512             // Compute where we are in the effect (scale is 0->1024)
   3513             lum_factor = (M4OSA_Int32)( percentageDone * 1024 );
   3514             // Apply the darkening effect
   3515             err = applyLumaEffect(M4VSS3GPP_kVideoEffectType_FadeFromBlack,
   3516                   planeIn, planeOut, (M4VIFI_UInt8 *)finalOutputBuffer,
   3517                   (M4VIFI_UInt8 *)tempOutputBuffer, lum_factor);
   3518             if(err != M4NO_ERROR) {
   3519                 return err;
   3520             }
   3521         }
   3522     }
   3523 
   3524     if(params->currentVideoEffect & VIDEO_EFFECT_FADETOBLACK) {
   3525         // Find the effect in effectSettings array
   3526         for(i=0;i<params->numberEffects;i++) {
   3527             if(params->effectsSettings[i].VideoEffectType ==
   3528              M4VSS3GPP_kVideoEffectType_FadeToBlack)
   3529                 break;
   3530         }
   3531         if(i < params->numberEffects) {
   3532             computePercentageDone(params->timeMs,
   3533              params->effectsSettings[i].uiStartTime,
   3534              params->effectsSettings[i].uiDuration, &percentageDone);
   3535 
   3536             // Compute where we are in the effect (scale is 0->1024)
   3537             lum_factor = (M4OSA_Int32)( (1.0-percentageDone) * 1024 );
   3538             // Apply the darkening effect
   3539             err = applyLumaEffect(M4VSS3GPP_kVideoEffectType_FadeToBlack,
   3540                   planeIn, planeOut, (M4VIFI_UInt8 *)finalOutputBuffer,
   3541                   (M4VIFI_UInt8 *)tempOutputBuffer, lum_factor);
   3542             if(err != M4NO_ERROR) {
   3543                 return err;
   3544             }
   3545         }
   3546     }
   3547 
   3548     LOGV("doMediaRendering CALL getBuffer()");
   3549     // Set the output YUV420 plane to be compatible with YV12 format
   3550     // W & H even
   3551     // YVU instead of YUV
   3552     // align buffers on 32 bits
   3553 
   3554     // Y plane
   3555     //in YV12 format, sizes must be even
   3556     M4OSA_UInt32 yv12PlaneWidth = ((params->outVideoWidth +1)>>1)<<1;
   3557     M4OSA_UInt32 yv12PlaneHeight = ((params->outVideoHeight+1)>>1)<<1;
   3558 
   3559     prepareYV12ImagePlane(planeOut, yv12PlaneWidth, yv12PlaneHeight,
   3560      (M4OSA_UInt32)params->outBufferStride, (M4VIFI_UInt8 *)params->pOutBuffer);
   3561 
   3562     err = applyRenderingMode(planeIn, planeOut, params->renderingMode);
   3563 
   3564     if(M4OSA_NULL != finalOutputBuffer) {
   3565         free(finalOutputBuffer);
   3566         finalOutputBuffer= M4OSA_NULL;
   3567     }
   3568     if(M4OSA_NULL != tempOutputBuffer) {
   3569         free(tempOutputBuffer);
   3570         tempOutputBuffer = M4OSA_NULL;
   3571     }
   3572     if(err != M4NO_ERROR) {
   3573         LOGV("doVideoPostProcessing: applyRenderingMode returned err=%d",err);
   3574         return err;
   3575     }
   3576     return M4NO_ERROR;
   3577 }
   3578 
   3579 android::status_t getVideoSizeByResolution(
   3580                       M4VIDEOEDITING_VideoFrameSize resolution,
   3581                       uint32_t *pWidth, uint32_t *pHeight) {
   3582 
   3583     uint32_t frameWidth, frameHeight;
   3584 
   3585     if (pWidth == NULL) {
   3586         LOGE("getVideoFrameSizeByResolution invalid pointer for pWidth");
   3587         return android::BAD_VALUE;
   3588     }
   3589     if (pHeight == NULL) {
   3590         LOGE("getVideoFrameSizeByResolution invalid pointer for pHeight");
   3591         return android::BAD_VALUE;
   3592     }
   3593 
   3594     switch (resolution) {
   3595         case M4VIDEOEDITING_kSQCIF:
   3596             frameWidth = 128;
   3597             frameHeight = 96;
   3598             break;
   3599 
   3600         case M4VIDEOEDITING_kQQVGA:
   3601             frameWidth = 160;
   3602             frameHeight = 120;
   3603             break;
   3604 
   3605         case M4VIDEOEDITING_kQCIF:
   3606             frameWidth = 176;
   3607             frameHeight = 144;
   3608             break;
   3609 
   3610         case M4VIDEOEDITING_kQVGA:
   3611             frameWidth = 320;
   3612             frameHeight = 240;
   3613             break;
   3614 
   3615         case M4VIDEOEDITING_kCIF:
   3616             frameWidth = 352;
   3617             frameHeight = 288;
   3618             break;
   3619 
   3620         case M4VIDEOEDITING_kVGA:
   3621             frameWidth = 640;
   3622             frameHeight = 480;
   3623             break;
   3624 
   3625         case M4VIDEOEDITING_kWVGA:
   3626             frameWidth = 800;
   3627             frameHeight = 480;
   3628             break;
   3629 
   3630         case M4VIDEOEDITING_kNTSC:
   3631             frameWidth = 720;
   3632             frameHeight = 480;
   3633             break;
   3634 
   3635         case M4VIDEOEDITING_k640_360:
   3636             frameWidth = 640;
   3637             frameHeight = 360;
   3638             break;
   3639 
   3640         case M4VIDEOEDITING_k854_480:
   3641             frameWidth = 854;
   3642             frameHeight = 480;
   3643             break;
   3644 
   3645         case M4VIDEOEDITING_k1280_720:
   3646             frameWidth = 1280;
   3647             frameHeight = 720;
   3648             break;
   3649 
   3650         case M4VIDEOEDITING_k1080_720:
   3651             frameWidth = 1080;
   3652             frameHeight = 720;
   3653             break;
   3654 
   3655         case M4VIDEOEDITING_k960_720:
   3656             frameWidth = 960;
   3657             frameHeight = 720;
   3658             break;
   3659 
   3660         case M4VIDEOEDITING_k1920_1080:
   3661             frameWidth = 1920;
   3662             frameHeight = 1080;
   3663             break;
   3664 
   3665         default:
   3666             LOGE("Unsupported video resolution %d.", resolution);
   3667             return android::BAD_VALUE;
   3668     }
   3669 
   3670     *pWidth = frameWidth;
   3671     *pHeight = frameHeight;
   3672 
   3673     return android::OK;
   3674 }
   3675 
   3676 M4VIFI_UInt8 M4VIFI_Rotate90LeftYUV420toYUV420(void* pUserData,
   3677     M4VIFI_ImagePlane *pPlaneIn, M4VIFI_ImagePlane *pPlaneOut) {
   3678 
   3679     M4VIFI_Int32 plane_number;
   3680     M4VIFI_UInt32 i,j, u_stride;
   3681     M4VIFI_UInt8 *p_buf_src, *p_buf_dest;
   3682 
   3683     /**< Loop on Y,U and V planes */
   3684     for (plane_number = 0; plane_number < 3; plane_number++) {
   3685         /**< Get adresses of first valid pixel in input and output buffer */
   3686         /**< As we have a -90 rotation, first needed pixel is the upper-right one */
   3687         p_buf_src =
   3688             &(pPlaneIn[plane_number].pac_data[pPlaneIn[plane_number].u_topleft]) +
   3689              pPlaneOut[plane_number].u_height - 1 ;
   3690         p_buf_dest =
   3691             &(pPlaneOut[plane_number].pac_data[pPlaneOut[plane_number].u_topleft]);
   3692         u_stride = pPlaneIn[plane_number].u_stride;
   3693         /**< Loop on output rows */
   3694         for (i = 0; i < pPlaneOut[plane_number].u_height; i++) {
   3695             /**< Loop on all output pixels in a row */
   3696             for (j = 0; j < pPlaneOut[plane_number].u_width; j++) {
   3697                 *p_buf_dest++= *p_buf_src;
   3698                 p_buf_src += u_stride;  /**< Go to the next row */
   3699             }
   3700 
   3701             /**< Go on next row of the output frame */
   3702             p_buf_dest +=
   3703                 pPlaneOut[plane_number].u_stride - pPlaneOut[plane_number].u_width;
   3704             /**< Go to next pixel in the last row of the input frame*/
   3705             p_buf_src -=
   3706                 pPlaneIn[plane_number].u_stride * pPlaneOut[plane_number].u_width + 1 ;
   3707         }
   3708     }
   3709 
   3710     return M4VIFI_OK;
   3711 }
   3712 
   3713 M4VIFI_UInt8 M4VIFI_Rotate90RightYUV420toYUV420(void* pUserData,
   3714     M4VIFI_ImagePlane *pPlaneIn, M4VIFI_ImagePlane *pPlaneOut) {
   3715 
   3716     M4VIFI_Int32 plane_number;
   3717     M4VIFI_UInt32 i,j, u_stride;
   3718     M4VIFI_UInt8 *p_buf_src, *p_buf_dest;
   3719 
   3720     /**< Loop on Y,U and V planes */
   3721     for (plane_number = 0; plane_number < 3; plane_number++) {
   3722         /**< Get adresses of first valid pixel in input and output buffer */
   3723         /**< As we have a +90 rotation, first needed pixel is the left-down one */
   3724         p_buf_src =
   3725             &(pPlaneIn[plane_number].pac_data[pPlaneIn[plane_number].u_topleft]) +
   3726              (pPlaneIn[plane_number].u_stride * (pPlaneOut[plane_number].u_width - 1));
   3727         p_buf_dest =
   3728             &(pPlaneOut[plane_number].pac_data[pPlaneOut[plane_number].u_topleft]);
   3729         u_stride = pPlaneIn[plane_number].u_stride;
   3730         /**< Loop on output rows */
   3731         for (i = 0; i < pPlaneOut[plane_number].u_height; i++) {
   3732             /**< Loop on all output pixels in a row */
   3733             for (j = 0; j < pPlaneOut[plane_number].u_width; j++) {
   3734                 *p_buf_dest++= *p_buf_src;
   3735                 p_buf_src -= u_stride;  /**< Go to the previous row */
   3736             }
   3737 
   3738             /**< Go on next row of the output frame */
   3739             p_buf_dest +=
   3740                 pPlaneOut[plane_number].u_stride - pPlaneOut[plane_number].u_width;
   3741             /**< Go to next pixel in the last row of the input frame*/
   3742             p_buf_src +=
   3743                 pPlaneIn[plane_number].u_stride * pPlaneOut[plane_number].u_width +1 ;
   3744         }
   3745     }
   3746 
   3747     return M4VIFI_OK;
   3748 }
   3749 
   3750 M4VIFI_UInt8 M4VIFI_Rotate180YUV420toYUV420(void* pUserData,
   3751     M4VIFI_ImagePlane *pPlaneIn, M4VIFI_ImagePlane *pPlaneOut) {
   3752     M4VIFI_Int32 plane_number;
   3753     M4VIFI_UInt32 i,j;
   3754     M4VIFI_UInt8 *p_buf_src, *p_buf_dest, temp_pix1;
   3755 
   3756     /**< Loop on Y,U and V planes */
   3757     for (plane_number = 0; plane_number < 3; plane_number++) {
   3758         /**< Get adresses of first valid pixel in input and output buffer */
   3759         p_buf_src =
   3760             &(pPlaneIn[plane_number].pac_data[pPlaneIn[plane_number].u_topleft]);
   3761         p_buf_dest =
   3762             &(pPlaneOut[plane_number].pac_data[pPlaneOut[plane_number].u_topleft]);
   3763 
   3764         /**< If pPlaneIn = pPlaneOut, the algorithm will be different */
   3765         if (p_buf_src == p_buf_dest) {
   3766             /**< Get Address of last pixel in the last row of the frame */
   3767             p_buf_dest +=
   3768                 pPlaneOut[plane_number].u_stride*(pPlaneOut[plane_number].u_height-1) +
   3769                  pPlaneOut[plane_number].u_width - 1;
   3770 
   3771             /**< We loop (height/2) times on the rows.
   3772              * In case u_height is odd, the row at the middle of the frame
   3773              * has to be processed as must be mirrored */
   3774             for (i = 0; i < ((pPlaneOut[plane_number].u_height)>>1); i++) {
   3775                 for (j = 0; j < pPlaneOut[plane_number].u_width; j++) {
   3776                     temp_pix1= *p_buf_dest;
   3777                     *p_buf_dest--= *p_buf_src;
   3778                     *p_buf_src++ = temp_pix1;
   3779                 }
   3780                 /**< Go on next row in top of frame */
   3781                 p_buf_src +=
   3782                     pPlaneOut[plane_number].u_stride - pPlaneOut[plane_number].u_width;
   3783                 /**< Go to the last pixel in previous row in bottom of frame*/
   3784                 p_buf_dest -=
   3785                     pPlaneOut[plane_number].u_stride - pPlaneOut[plane_number].u_width;
   3786             }
   3787 
   3788             /**< Mirror middle row in case height is odd */
   3789             if ((pPlaneOut[plane_number].u_height%2)!= 0) {
   3790                 p_buf_src =
   3791                     &(pPlaneOut[plane_number].pac_data[pPlaneIn[plane_number].u_topleft]);
   3792                 p_buf_src +=
   3793                     pPlaneOut[plane_number].u_stride*(pPlaneOut[plane_number].u_height>>1);
   3794                 p_buf_dest =
   3795                     p_buf_src + pPlaneOut[plane_number].u_width;
   3796 
   3797                 /**< We loop u_width/2 times on this row.
   3798                  *  In case u_width is odd, the pixel at the middle of this row
   3799                  * remains unchanged */
   3800                 for (j = 0; j < (pPlaneOut[plane_number].u_width>>1); j++) {
   3801                     temp_pix1= *p_buf_dest;
   3802                     *p_buf_dest--= *p_buf_src;
   3803                     *p_buf_src++ = temp_pix1;
   3804                 }
   3805             }
   3806         } else {
   3807             /**< Get Address of last pixel in the last row of the output frame */
   3808             p_buf_dest +=
   3809                 pPlaneOut[plane_number].u_stride*(pPlaneOut[plane_number].u_height-1) +
   3810                  pPlaneIn[plane_number].u_width - 1;
   3811 
   3812             /**< Loop on rows */
   3813             for (i = 0; i < pPlaneOut[plane_number].u_height; i++) {
   3814                 for (j = 0; j < pPlaneOut[plane_number].u_width; j++) {
   3815                     *p_buf_dest--= *p_buf_src++;
   3816                 }
   3817 
   3818                 /**< Go on next row in top of input frame */
   3819                 p_buf_src +=
   3820                     pPlaneIn[plane_number].u_stride - pPlaneOut[plane_number].u_width;
   3821                 /**< Go to last pixel of previous row in bottom of input frame*/
   3822                 p_buf_dest -=
   3823                     pPlaneOut[plane_number].u_stride - pPlaneOut[plane_number].u_width;
   3824             }
   3825         }
   3826     }
   3827 
   3828     return M4VIFI_OK;
   3829 }
   3830 
   3831 M4OSA_ERR applyVideoRotation(M4OSA_Void* pBuffer, M4OSA_UInt32 width,
   3832                              M4OSA_UInt32 height, M4OSA_UInt32 rotation) {
   3833 
   3834     M4OSA_ERR err = M4NO_ERROR;
   3835     M4VIFI_ImagePlane planeIn[3], planeOut[3];
   3836 
   3837     if (pBuffer == M4OSA_NULL) {
   3838         LOGE("applyVideoRotation: NULL input frame");
   3839         return M4ERR_PARAMETER;
   3840     }
   3841     M4OSA_UInt8* outPtr = (M4OSA_UInt8 *)M4OSA_32bitAlignedMalloc(
   3842      (width*height*1.5), M4VS, (M4OSA_Char*)("rotation out ptr"));
   3843     if (outPtr == M4OSA_NULL) {
   3844         return M4ERR_ALLOC;
   3845     }
   3846 
   3847     // In plane
   3848     prepareYUV420ImagePlane(planeIn, width,
   3849         height, (M4VIFI_UInt8 *)pBuffer, width, height);
   3850 
   3851     // Out plane
   3852     if (rotation != 180) {
   3853         prepareYUV420ImagePlane(planeOut, height,
   3854             width, outPtr, height, width);
   3855     }
   3856 
   3857     switch(rotation) {
   3858         case 90:
   3859             M4VIFI_Rotate90RightYUV420toYUV420(M4OSA_NULL, planeIn, planeOut);
   3860             memset(pBuffer, 0, (width*height*1.5));
   3861             memcpy(pBuffer, (void *)outPtr, (width*height*1.5));
   3862             break;
   3863 
   3864         case 180:
   3865             // In plane rotation, so planeOut = planeIn
   3866             M4VIFI_Rotate180YUV420toYUV420(M4OSA_NULL, planeIn, planeIn);
   3867             break;
   3868 
   3869         case 270:
   3870             M4VIFI_Rotate90LeftYUV420toYUV420(M4OSA_NULL, planeIn, planeOut);
   3871             memset(pBuffer, 0, (width*height*1.5));
   3872             memcpy(pBuffer, (void *)outPtr, (width*height*1.5));
   3873             break;
   3874 
   3875         default:
   3876             LOGE("invalid rotation param %d", (int)rotation);
   3877             err = M4ERR_PARAMETER;
   3878             break;
   3879     }
   3880 
   3881     free((void *)outPtr);
   3882     return err;
   3883 
   3884 }
   3885 
   3886