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