• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
M4VIFI_YUV420PlanarToYUV420Semiplanar(void * user_data,M4VIFI_ImagePlane * PlaneIn,M4VIFI_ImagePlane * PlaneOut)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 
M4VIFI_SemiplanarYUV420toYUV420(void * user_data,M4VIFI_ImagePlane * PlaneIn,M4VIFI_ImagePlane * PlaneOut)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 */
M4VSS3GPP_externalVideoEffectColor(M4OSA_Void * pFunctionContext,M4VIFI_ImagePlane * PlaneIn,M4VIFI_ImagePlane * PlaneOut,M4VSS3GPP_ExternalProgress * pProgress,M4OSA_UInt32 uiEffectKind)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 */
M4VSS3GPP_externalVideoEffectFraming(M4OSA_Void * userData,M4VIFI_ImagePlane PlaneIn[3],M4VIFI_ImagePlane * PlaneOut,M4VSS3GPP_ExternalProgress * pProgress,M4OSA_UInt32 uiEffectKind)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 */
M4VSS3GPP_externalVideoEffectFifties(M4OSA_Void * pUserData,M4VIFI_ImagePlane * pPlaneIn,M4VIFI_ImagePlane * pPlaneOut,M4VSS3GPP_ExternalProgress * pProgress,M4OSA_UInt32 uiEffectKind)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 
M4VFL_modifyLumaWithScale(M4ViComImagePlane * plane_in,M4ViComImagePlane * plane_out,unsigned long lum_factor,void * user_data)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 */
M4xVSS_internalConvertRGBtoYUV(M4xVSS_FramingStruct * framingCtx)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 */
M4xVSS_internalConvertRGB888toYUV(M4xVSS_FramingStruct * framingCtx)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 */
M4VIFI_xVSS_RGB565toYUV420(void * pUserData,M4VIFI_ImagePlane * pPlaneIn,M4VIFI_ImagePlane * pPlaneOut)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 ***************************************************************************/
M4VIFI_RGB888toYUV420(void * pUserData,M4VIFI_ImagePlane * PlaneIn,M4VIFI_ImagePlane PlaneOut[3])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 
M4VIFI_YUV420toYUV420(void * user_data,M4VIFI_ImagePlane PlaneIn[3],M4VIFI_ImagePlane * PlaneOut)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 */
M4VIFI_ResizeBilinearYUV420toYUV420(void * pUserData,M4VIFI_ImagePlane * pPlaneIn,M4VIFI_ImagePlane * pPlaneOut)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 
applyRenderingMode(M4VIFI_ImagePlane * pPlaneIn,M4VIFI_ImagePlane * pPlaneOut,M4xVSS_MediaRendering mediaRendering)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 */
M4AIR_create(M4OSA_Context * pContext,M4AIR_InputFormatType inputFormat)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 */
M4AIR_cleanUp(M4OSA_Context pContext)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 */
M4AIR_configure(M4OSA_Context pContext,M4AIR_Params * pParams)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 */
M4AIR_get(M4OSA_Context pContext,M4VIFI_ImagePlane * pIn,M4VIFI_ImagePlane * pOut)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 */
LvGetImageThumbNail(const char * fileName,M4OSA_UInt32 height,M4OSA_UInt32 width,M4OSA_Void ** pBuffer)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         ALOGE("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         ALOGE("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         ALOGE("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         ALOGE("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         ALOGE("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             ALOGE("error when converting from RGB to YUV: 0x%x\n", (unsigned int)err);
2944         }
2945         free(rgbPlane.pac_data);
2946 
2947         //ALOGE("RGB to YUV done");
2948 #ifdef FILE_DUMP
2949         FILE *fp1 = fopen("/sdcard/Input/test_yuv.raw", "wb");
2950         if(fp1 == NULL)
2951             ALOGE("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 }
prepareYUV420ImagePlane(M4VIFI_ImagePlane * plane,M4OSA_UInt32 width,M4OSA_UInt32 height,M4VIFI_UInt8 * buffer,M4OSA_UInt32 reportedWidth,M4OSA_UInt32 reportedHeight)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 
prepareYV12ImagePlane(M4VIFI_ImagePlane * plane,M4OSA_UInt32 width,M4OSA_UInt32 height,M4OSA_UInt32 stride,M4VIFI_UInt8 * buffer)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 
swapImagePlanes(M4VIFI_ImagePlane * planeIn,M4VIFI_ImagePlane * planeOut,M4VIFI_UInt8 * buffer1,M4VIFI_UInt8 * buffer2)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 
computePercentageDone(M4OSA_UInt32 ctsMs,M4OSA_UInt32 effectStartTimeMs,M4OSA_UInt32 effectDuration,M4OSA_Double * percentageDone)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 
computeProgressForVideoEffect(M4OSA_UInt32 ctsMs,M4OSA_UInt32 effectStartTimeMs,M4OSA_UInt32 effectDuration,M4VSS3GPP_ExternalProgress * extProgress)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 
prepareFramingStructure(M4xVSS_FramingStruct * framingCtx,M4VSS3GPP_EffectSettings * effectsSettings,M4OSA_UInt32 index,M4VIFI_UInt8 * overlayRGB,M4VIFI_UInt8 * overlayYUV)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         ALOGV(" 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 
applyColorEffect(M4xVSS_VideoEffectType colorEffect,M4VIFI_ImagePlane * planeIn,M4VIFI_ImagePlane * planeOut,M4VIFI_UInt8 * buffer1,M4VIFI_UInt8 * buffer2,M4OSA_UInt16 rgbColorData)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         ALOGV("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 
applyLumaEffect(M4VSS3GPP_VideoEffectType videoEffect,M4VIFI_ImagePlane * planeIn,M4VIFI_ImagePlane * planeOut,M4VIFI_UInt8 * buffer1,M4VIFI_UInt8 * buffer2,M4OSA_Int32 lum_factor)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         ALOGE("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 
applyEffectsAndRenderingMode(vePostProcessParams * params,M4OSA_UInt32 reportedWidth,M4OSA_UInt32 reportedHeight)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         ALOGE("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         ALOGE("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                 ALOGE("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     ALOGV("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         ALOGV("doVideoPostProcessing: applyRenderingMode returned err=%d",err);
3574         return err;
3575     }
3576     return M4NO_ERROR;
3577 }
3578 
getVideoSizeByResolution(M4VIDEOEDITING_VideoFrameSize resolution,uint32_t * pWidth,uint32_t * pHeight)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         ALOGE("getVideoFrameSizeByResolution invalid pointer for pWidth");
3587         return android::BAD_VALUE;
3588     }
3589     if (pHeight == NULL) {
3590         ALOGE("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             ALOGE("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 
M4VIFI_Rotate90LeftYUV420toYUV420(void * pUserData,M4VIFI_ImagePlane * pPlaneIn,M4VIFI_ImagePlane * pPlaneOut)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 
M4VIFI_Rotate90RightYUV420toYUV420(void * pUserData,M4VIFI_ImagePlane * pPlaneIn,M4VIFI_ImagePlane * pPlaneOut)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 
M4VIFI_Rotate180YUV420toYUV420(void * pUserData,M4VIFI_ImagePlane * pPlaneIn,M4VIFI_ImagePlane * pPlaneOut)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 
applyVideoRotation(M4OSA_Void * pBuffer,M4OSA_UInt32 width,M4OSA_UInt32 height,M4OSA_UInt32 rotation)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         ALOGE("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             memcpy(pBuffer, (void *)outPtr, (width*height*1.5));
3861             break;
3862 
3863         case 180:
3864             // In plane rotation, so planeOut = planeIn
3865             M4VIFI_Rotate180YUV420toYUV420(M4OSA_NULL, planeIn, planeIn);
3866             break;
3867 
3868         case 270:
3869             M4VIFI_Rotate90LeftYUV420toYUV420(M4OSA_NULL, planeIn, planeOut);
3870             memcpy(pBuffer, (void *)outPtr, (width*height*1.5));
3871             break;
3872 
3873         default:
3874             ALOGE("invalid rotation param %d", (int)rotation);
3875             err = M4ERR_PARAMETER;
3876             break;
3877     }
3878 
3879     free((void *)outPtr);
3880     return err;
3881 
3882 }
3883 
3884