1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 /**
17 ******************************************************************************
18 * @file M4TRAN_transition.c
19 * @brief
20 ******************************************************************************
21 */
22
23 /**
24 * OSAL (memset and memcpy) ***/
25 #include "M4OSA_Memory.h"
26
27 #include "M4VFL_transition.h"
28
29 #include <string.h>
30
31 #ifdef LITTLE_ENDIAN
32 #define M4VFL_SWAP_SHORT(a) a = ((a & 0xFF) << 8) | ((a & 0xFF00) >> 8)
33 #else
34 #define M4VFL_SWAP_SHORT(a)
35 #endif
36
37 #define LUM_FACTOR_MAX 10
38
39
M4VFL_modifyLumaByStep(M4ViComImagePlane * plane_in,M4ViComImagePlane * plane_out,M4VFL_ModifLumParam * lum_param,void * user_data)40 unsigned char M4VFL_modifyLumaByStep(M4ViComImagePlane *plane_in, M4ViComImagePlane *plane_out,
41 M4VFL_ModifLumParam *lum_param, void *user_data)
42 {
43 unsigned short *p_src, *p_dest, *p_src_line, *p_dest_line;
44 unsigned long pix_src;
45 unsigned long u_outpx, u_outpx2;
46 unsigned long u_width, u_stride, u_stride_out,u_height, pix;
47 unsigned long lf1, lf2, lf3;
48 long i, j;
49
50 if (lum_param->copy_chroma != 0)
51 {
52 /* copy chroma plane */
53
54 }
55
56 /* apply luma factor */
57 u_width = plane_in[0].u_width;
58 u_height = plane_in[0].u_height;
59 u_stride = (plane_in[0].u_stride >> 1);
60 u_stride_out = (plane_out[0].u_stride >> 1);
61 p_dest = (unsigned short *) &plane_out[0].pac_data[plane_out[0].u_topleft];
62 p_src = (unsigned short *) &plane_in[0].pac_data[plane_in[0].u_topleft];
63 p_dest_line = p_dest;
64 p_src_line = p_src;
65
66 switch(lum_param->lum_factor)
67 {
68 case 0:
69 /* very specific case : set luma plane to 16 */
70 for (j = u_height; j != 0; j--)
71 {
72 memset((void *)p_dest,16, u_width);
73 p_dest += u_stride_out;
74 }
75 return 0;
76
77 case 1:
78 /* 0.25 */
79 lf1 = 6; lf2 = 6; lf3 = 7;
80 break;
81 case 2:
82 /* 0.375 */
83 lf1 = 7; lf2 = 7; lf3 = 7;
84 break;
85 case 3:
86 /* 0.5 */
87 lf1 = 7; lf2 = 7; lf3 = 8;
88 break;
89 case 4:
90 /* 0.625 */
91 lf1 = 7; lf2 = 8; lf3 = 8;
92 break;
93 case 5:
94 /* 0.75 */
95 lf1 = 8; lf2 = 8; lf3 = 8;
96 break;
97 case 6:
98 /* 0.875 */
99 lf1 = 9; lf2 = 8; lf3 = 7;
100 break;
101 default:
102 lf1 = 8; lf2 = 8; lf3 = 9;
103 break;
104 }
105
106 for (j = u_height; j != 0; j--)
107 {
108 p_dest = p_dest_line;
109 p_src = p_src_line;
110 for (i = (u_width >> 1); i != 0; i--)
111 {
112 pix_src = (unsigned long) *p_src++;
113 pix = pix_src & 0xFF;
114 u_outpx = (((pix << lf1) + (pix << lf2) + (pix << lf3) ) >> LUM_FACTOR_MAX);
115 pix = ((pix_src & 0xFF00) >> 8);
116 u_outpx2 = ((((pix << lf1) + (pix << lf2) + (pix << lf3) ) >> LUM_FACTOR_MAX)<< 8) ;
117 *p_dest++ = (unsigned short) (u_outpx2 | u_outpx);
118 }
119 p_dest_line += u_stride_out;
120 p_src_line += u_stride;
121 }
122 return 0;
123 }
124
125
M4VFL_modifyLumaWithScale(M4ViComImagePlane * plane_in,M4ViComImagePlane * plane_out,unsigned long lum_factor,void * user_data)126 unsigned char M4VFL_modifyLumaWithScale(M4ViComImagePlane *plane_in,
127 M4ViComImagePlane *plane_out,
128 unsigned long lum_factor,
129 void *user_data)
130 {
131 unsigned short *p_src, *p_dest, *p_src_line, *p_dest_line;
132 unsigned char *p_csrc, *p_cdest, *p_csrc_line, *p_cdest_line;
133 unsigned long pix_src;
134 unsigned long u_outpx, u_outpx2;
135 unsigned long u_width, u_stride, u_stride_out,u_height, pix;
136 long i, j;
137
138 /* copy or filter chroma */
139 u_width = plane_in[1].u_width;
140 u_height = plane_in[1].u_height;
141 u_stride = plane_in[1].u_stride;
142 u_stride_out = plane_out[1].u_stride;
143 p_cdest_line = (unsigned char *) &plane_out[1].pac_data[plane_out[1].u_topleft];
144 p_csrc_line = (unsigned char *) &plane_in[1].pac_data[plane_in[1].u_topleft];
145
146 if (lum_factor > 256)
147 {
148 p_cdest = (unsigned char *) &plane_out[2].pac_data[plane_out[2].u_topleft];
149 p_csrc = (unsigned char *) &plane_in[2].pac_data[plane_in[2].u_topleft];
150 /* copy chroma */
151 for (j = u_height; j != 0; j--)
152 {
153 for (i = u_width; i != 0; i--)
154 {
155 memcpy((void *)p_cdest_line, (void *)p_csrc_line, u_width);
156 memcpy((void *)p_cdest,(void *) p_csrc, u_width);
157 }
158 p_cdest_line += u_stride_out;
159 p_cdest += u_stride_out;
160 p_csrc_line += u_stride;
161 p_csrc += u_stride;
162 }
163 }
164 else
165 {
166 /* filter chroma */
167 pix = (1024 - lum_factor) << 7;
168 for (j = u_height; j != 0; j--)
169 {
170 p_cdest = p_cdest_line;
171 p_csrc = p_csrc_line;
172 for (i = u_width; i != 0; i--)
173 {
174 *p_cdest++ = ((pix + (*p_csrc++ & 0xFF) * lum_factor) >> LUM_FACTOR_MAX);
175 }
176 p_cdest_line += u_stride_out;
177 p_csrc_line += u_stride;
178 }
179 p_cdest_line = (unsigned char *) &plane_out[2].pac_data[plane_out[2].u_topleft];
180 p_csrc_line = (unsigned char *) &plane_in[2].pac_data[plane_in[2].u_topleft];
181 for (j = u_height; j != 0; j--)
182 {
183 p_cdest = p_cdest_line;
184 p_csrc = p_csrc_line;
185 for (i = u_width; i != 0; i--)
186 {
187 *p_cdest++ = ((pix + (*p_csrc & 0xFF) * lum_factor) >> LUM_FACTOR_MAX);
188 }
189 p_cdest_line += u_stride_out;
190 p_csrc_line += u_stride;
191 }
192 }
193 /* apply luma factor */
194 u_width = plane_in[0].u_width;
195 u_height = plane_in[0].u_height;
196 u_stride = (plane_in[0].u_stride >> 1);
197 u_stride_out = (plane_out[0].u_stride >> 1);
198 p_dest = (unsigned short *) &plane_out[0].pac_data[plane_out[0].u_topleft];
199 p_src = (unsigned short *) &plane_in[0].pac_data[plane_in[0].u_topleft];
200 p_dest_line = p_dest;
201 p_src_line = p_src;
202
203 for (j = u_height; j != 0; j--)
204 {
205 p_dest = p_dest_line;
206 p_src = p_src_line;
207 for (i = (u_width >> 1); i != 0; i--)
208 {
209 pix_src = (unsigned long) *p_src++;
210 pix = pix_src & 0xFF;
211 u_outpx = ((pix * lum_factor) >> LUM_FACTOR_MAX);
212 pix = ((pix_src & 0xFF00) >> 8);
213 u_outpx2 = (((pix * lum_factor) >> LUM_FACTOR_MAX)<< 8) ;
214 *p_dest++ = (unsigned short) (u_outpx2 | u_outpx);
215 }
216 p_dest_line += u_stride_out;
217 p_src_line += u_stride;
218 }
219
220 return 0;
221 }
222
223 /**
224 *************************************************************************************************
225 * M4OSA_ERR M4VIFI_ImageBlendingonYUV420 (void *pUserData,
226 * M4VIFI_ImagePlane *pPlaneIn1,
227 * M4VIFI_ImagePlane *pPlaneIn2,
228 * M4VIFI_ImagePlane *pPlaneOut,
229 * UInt32 Progress)
230 * @brief Blends two YUV 4:2:0 Planar images.
231 * @note Blends YUV420 planar images,
232 * Map the value of progress from (0 - 1000) to (0 - 1024)
233 * Set the range of blendingfactor,
234 * 1. from 0 to (Progress << 1) ;for Progress <= 512
235 * 2. from (( Progress - 512)<< 1) to 1024 ;otherwise
236 * Set the increment of blendingfactor for each element in the image row by the factor,
237 * = (Range-1) / (image width-1) ;for width >= range
238 * = (Range) / (image width) ;otherwise
239 * Loop on each(= i) row of output Y plane (steps of 2)
240 * Loop on each(= j) column of output Y plane (steps of 2)
241 * Get four Y samples and one U & V sample from two input YUV4:2:0 images and
242 * Compute four Y sample and one U & V sample for output YUV4:2:0 image
243 * using the following,
244 * Out(i,j) = blendingfactor(i,j) * In1(i,j)+ (l - blendingfactor(i,j)) *In2(i,j)
245 * end loop column
246 * end loop row.
247 * @param pUserData: (IN) User Specific Parameter
248 * @param pPlaneIn1: (IN) Pointer to an array of image plane structures maintained
249 * for Y, U and V planes.
250 * @param pPlaneIn2: (IN) Pointer to an array of image plane structures maintained
251 * for Y, U and V planes.
252 * @param pPlaneOut: (OUT) Pointer to an array of image plane structures maintained
253 * for Y, U and V planes.
254 * @param Progress: (IN) Progress value (varies between 0 and 1000)
255 * @return M4VIFI_OK: No error
256 * @return M4VIFI_ILLEGAL_FRAME_HEIGHT: Error in height
257 * @return M4VIFI_ILLEGAL_FRAME_WIDTH: Error in width
258 *************************************************************************************************
259 */
260
261 /** Check for value is EVEN */
262 #ifndef IS_EVEN
263 #define IS_EVEN(a) (!(a & 0x01))
264 #endif
265
266 /** Used for fixed point implementation */
267 #ifndef MAX_SHORT
268 #define MAX_SHORT 0x10000
269 #endif
270
271 #ifndef NULL
272 #define NULL 0
273 #endif
274
275 #ifndef FALSE
276 #define FALSE 0
277 #define TRUE !FALSE
278 #endif
279
M4VIFI_ImageBlendingonYUV420(void * pUserData,M4ViComImagePlane * pPlaneIn1,M4ViComImagePlane * pPlaneIn2,M4ViComImagePlane * pPlaneOut,UInt32 Progress)280 unsigned char M4VIFI_ImageBlendingonYUV420 (void *pUserData,
281 M4ViComImagePlane *pPlaneIn1,
282 M4ViComImagePlane *pPlaneIn2,
283 M4ViComImagePlane *pPlaneOut,
284 UInt32 Progress)
285 {
286 UInt8 *pu8_data_Y_start1,*pu8_data_U_start1,*pu8_data_V_start1;
287 UInt8 *pu8_data_Y_start2,*pu8_data_U_start2,*pu8_data_V_start2;
288 UInt8 *pu8_data_Y_start3,*pu8_data_U_start3,*pu8_data_V_start3;
289 UInt8 *pu8_data_Y_current1, *pu8_data_Y_next1, *pu8_data_U1, *pu8_data_V1;
290 UInt8 *pu8_data_Y_current2, *pu8_data_Y_next2, *pu8_data_U2, *pu8_data_V2;
291 UInt8 *pu8_data_Y_current3,*pu8_data_Y_next3, *pu8_data_U3, *pu8_data_V3;
292 UInt32 u32_stride_Y1, u32_stride2_Y1, u32_stride_U1, u32_stride_V1;
293 UInt32 u32_stride_Y2, u32_stride2_Y2, u32_stride_U2, u32_stride_V2;
294 UInt32 u32_stride_Y3, u32_stride2_Y3, u32_stride_U3, u32_stride_V3;
295 UInt32 u32_height, u32_width;
296 UInt32 u32_blendfactor, u32_startA, u32_endA, u32_blend_inc, u32_x_accum;
297 UInt32 u32_col, u32_row, u32_rangeA, u32_progress;
298 UInt32 u32_U1,u32_V1,u32_U2,u32_V2, u32_Y1, u32_Y2;
299
300
301 /* Check the Y plane height is EVEN and image plane heights are same */
302 if( (IS_EVEN(pPlaneIn1[0].u_height) == FALSE) ||
303 (IS_EVEN(pPlaneIn2[0].u_height) == FALSE) ||
304 (IS_EVEN(pPlaneOut[0].u_height) == FALSE) ||
305 (pPlaneIn1[0].u_height != pPlaneOut[0].u_height) ||
306 (pPlaneIn2[0].u_height != pPlaneOut[0].u_height) )
307 {
308 return M4VIFI_ILLEGAL_FRAME_HEIGHT;
309 }
310
311 /* Check the Y plane width is EVEN and image plane widths are same */
312 if( (IS_EVEN(pPlaneIn1[0].u_width) == FALSE) ||
313 (IS_EVEN(pPlaneIn2[0].u_width) == FALSE) ||
314 (IS_EVEN(pPlaneOut[0].u_width) == FALSE) ||
315 (pPlaneIn1[0].u_width != pPlaneOut[0].u_width) ||
316 (pPlaneIn2[0].u_width != pPlaneOut[0].u_width) )
317 {
318 return M4VIFI_ILLEGAL_FRAME_WIDTH;
319 }
320
321 /* Set the pointer to the beginning of the input1 YUV420 image planes */
322 pu8_data_Y_start1 = pPlaneIn1[0].pac_data + pPlaneIn1[0].u_topleft;
323 pu8_data_U_start1 = pPlaneIn1[1].pac_data + pPlaneIn1[1].u_topleft;
324 pu8_data_V_start1 = pPlaneIn1[2].pac_data + pPlaneIn1[2].u_topleft;
325
326 /* Set the pointer to the beginning of the input2 YUV420 image planes */
327 pu8_data_Y_start2 = pPlaneIn2[0].pac_data + pPlaneIn2[0].u_topleft;
328 pu8_data_U_start2 = pPlaneIn2[1].pac_data + pPlaneIn2[1].u_topleft;
329 pu8_data_V_start2 = pPlaneIn2[2].pac_data + pPlaneIn2[2].u_topleft;
330
331 /* Set the pointer to the beginning of the output YUV420 image planes */
332 pu8_data_Y_start3 = pPlaneOut[0].pac_data + pPlaneOut[0].u_topleft;
333 pu8_data_U_start3 = pPlaneOut[1].pac_data + pPlaneOut[1].u_topleft;
334 pu8_data_V_start3 = pPlaneOut[2].pac_data + pPlaneOut[2].u_topleft;
335
336 /* Set the stride for the next row in each input1 YUV420 plane */
337 u32_stride_Y1 = pPlaneIn1[0].u_stride;
338 u32_stride_U1 = pPlaneIn1[1].u_stride;
339 u32_stride_V1 = pPlaneIn1[2].u_stride;
340
341 /* Set the stride for the next row in each input2 YUV420 plane */
342 u32_stride_Y2 = pPlaneIn2[0].u_stride;
343 u32_stride_U2 = pPlaneIn2[1].u_stride;
344 u32_stride_V2 = pPlaneIn2[2].u_stride;
345
346 /* Set the stride for the next row in each output YUV420 plane */
347 u32_stride_Y3 = pPlaneOut[0].u_stride;
348 u32_stride_U3 = pPlaneOut[1].u_stride;
349 u32_stride_V3 = pPlaneOut[2].u_stride;
350
351 u32_stride2_Y1 = u32_stride_Y1 << 1;
352 u32_stride2_Y2 = u32_stride_Y2 << 1;
353 u32_stride2_Y3 = u32_stride_Y3 << 1;
354
355 /* Get the size of the output image */
356 u32_height = pPlaneOut[0].u_height;
357 u32_width = pPlaneOut[0].u_width;
358
359 /* User Specified Progress value */
360 u32_progress = Progress;
361
362 /* Map Progress value from (0 - 1000) to (0 - 1024) -> for optimisation */
363 if(u32_progress < 1000)
364 u32_progress = ((u32_progress << 10) / 1000);
365 else
366 u32_progress = 1024;
367
368 /* Set the range of blendingfactor */
369 if(u32_progress <= 512)
370 {
371 u32_startA = 0;
372 u32_endA = (u32_progress << 1);
373 }
374 else /* u32_progress > 512 */
375 {
376 u32_startA = (u32_progress - 512) << 1;
377 u32_endA = 1024;
378 }
379 u32_rangeA = u32_endA - u32_startA;
380
381 /* Set the increment of blendingfactor for each element in the image row */
382 if ((u32_width >= u32_rangeA) && (u32_rangeA > 0) )
383 {
384 u32_blend_inc = ((u32_rangeA-1) * MAX_SHORT) / (u32_width - 1);
385 }
386 else /* (u32_width < u32_rangeA) || (u32_rangeA < 0) */
387 {
388 u32_blend_inc = (u32_rangeA * MAX_SHORT) / (u32_width);
389 }
390
391 /* Two YUV420 rows are computed at each pass */
392 for (u32_row = u32_height; u32_row != 0; u32_row -=2)
393 {
394 /* Set pointers to the beginning of the row for each input image1 plane */
395 pu8_data_Y_current1 = pu8_data_Y_start1;
396 pu8_data_U1 = pu8_data_U_start1;
397 pu8_data_V1 = pu8_data_V_start1;
398
399 /* Set pointers to the beginning of the row for each input image2 plane */
400 pu8_data_Y_current2 = pu8_data_Y_start2;
401 pu8_data_U2 = pu8_data_U_start2;
402 pu8_data_V2 = pu8_data_V_start2;
403
404 /* Set pointers to the beginning of the row for each output image plane */
405 pu8_data_Y_current3 = pu8_data_Y_start3;
406 pu8_data_U3 = pu8_data_U_start3;
407 pu8_data_V3 = pu8_data_V_start3;
408
409 /* Set pointers to the beginning of the next row for image luma plane */
410 pu8_data_Y_next1 = pu8_data_Y_current1 + u32_stride_Y1;
411 pu8_data_Y_next2 = pu8_data_Y_current2 + u32_stride_Y2;
412 pu8_data_Y_next3 = pu8_data_Y_current3 + u32_stride_Y3;
413
414 /* Initialise blendfactor */
415 u32_blendfactor = u32_startA;
416 /* Blendfactor Increment accumulator */
417 u32_x_accum = 0;
418
419 /* Loop on each column of the output image */
420 for (u32_col = u32_width; u32_col != 0 ; u32_col -=2)
421 {
422 /* Update the blending factor */
423 u32_blendfactor = u32_startA + (u32_x_accum >> 16);
424
425 /* Get Luma value (x,y) of input Image1 */
426 u32_Y1 = *pu8_data_Y_current1++;
427
428 /* Get chrominance2 value */
429 u32_U1 = *pu8_data_U1++;
430 u32_V1 = *pu8_data_V1++;
431
432 /* Get Luma value (x,y) of input Image2 */
433 u32_Y2 = *pu8_data_Y_current2++;
434
435 /* Get chrominance2 value */
436 u32_U2 = *pu8_data_U2++;
437 u32_V2 = *pu8_data_V2++;
438
439 /* Compute Luma value (x,y) of Output image */
440 *pu8_data_Y_current3++ = (UInt8)((u32_blendfactor * u32_Y2 +
441 (1024 - u32_blendfactor)*u32_Y1) >> 10);
442 /* Compute chroma(U) value of Output image */
443 *pu8_data_U3++ = (UInt8)((u32_blendfactor * u32_U2 +
444 (1024 - u32_blendfactor)*u32_U1) >> 10);
445 /* Compute chroma(V) value of Output image */
446 *pu8_data_V3++ = (UInt8)((u32_blendfactor * u32_V2 +
447 (1024 - u32_blendfactor)*u32_V1) >> 10);
448
449 /* Get Luma value (x,y+1) of input Image1 */
450 u32_Y1 = *pu8_data_Y_next1++;
451
452 /* Get Luma value (x,y+1) of input Image2 */
453 u32_Y2 = *pu8_data_Y_next2++;
454
455 /* Compute Luma value (x,y+1) of Output image*/
456 *pu8_data_Y_next3++ = (UInt8)((u32_blendfactor * u32_Y2 +
457 (1024 - u32_blendfactor)*u32_Y1) >> 10);
458 /* Update accumulator */
459 u32_x_accum += u32_blend_inc;
460
461 /* Update the blending factor */
462 u32_blendfactor = u32_startA + (u32_x_accum >> 16);
463
464 /* Get Luma value (x+1,y) of input Image1 */
465 u32_Y1 = *pu8_data_Y_current1++;
466
467 /* Get Luma value (x+1,y) of input Image2 */
468 u32_Y2 = *pu8_data_Y_current2++;
469
470 /* Compute Luma value (x+1,y) of Output image*/
471 *pu8_data_Y_current3++ = (UInt8)((u32_blendfactor * u32_Y2 +
472 (1024 - u32_blendfactor)*u32_Y1) >> 10);
473
474 /* Get Luma value (x+1,y+1) of input Image1 */
475 u32_Y1 = *pu8_data_Y_next1++;
476
477 /* Get Luma value (x+1,y+1) of input Image2 */
478 u32_Y2 = *pu8_data_Y_next2++;
479
480 /* Compute Luma value (x+1,y+1) of Output image*/
481 *pu8_data_Y_next3++ = (UInt8)((u32_blendfactor * u32_Y2 +
482 (1024 - u32_blendfactor)*u32_Y1) >> 10);
483 /* Update accumulator */
484 u32_x_accum += u32_blend_inc;
485
486 /* Working pointers are incremented just after each storage */
487
488 }/* End of row scanning */
489
490 /* Update working pointer of input image1 for next row */
491 pu8_data_Y_start1 += u32_stride2_Y1;
492 pu8_data_U_start1 += u32_stride_U1;
493 pu8_data_V_start1 += u32_stride_V1;
494
495 /* Update working pointer of input image2 for next row */
496 pu8_data_Y_start2 += u32_stride2_Y2;
497 pu8_data_U_start2 += u32_stride_U2;
498 pu8_data_V_start2 += u32_stride_V2;
499
500 /* Update working pointer of output image for next row */
501 pu8_data_Y_start3 += u32_stride2_Y3;
502 pu8_data_U_start3 += u32_stride_U3;
503 pu8_data_V_start3 += u32_stride_V3;
504
505 }/* End of column scanning */
506
507 return M4VIFI_OK;
508 }
509 /* End of file M4VIFI_ImageBlendingonYUV420.c */
510
511