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