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