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