1 /******************************************************************************
2  *
3  * Copyright (C) 2015 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  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20 /**
21 *******************************************************************************
22 * @file
23 *  impeg2d_mcu.c
24 *
25 * @brief
26 *  Contains MC function definitions for MPEG2 decoder
27 *
28 * @author
29 *  Harish
30 *
31 * @par List of Functions:
32 * - impeg2_copy_mb()
33 * - impeg2_interpolate()
34 * - impeg2_mc_halfx_halfy_8x8()
35 * - impeg2_mc_halfx_fully_8x8()
36 * - impeg2_mc_fullx_halfy_8x8()
37 * - impeg2_mc_fullx_fully_8x8()
38 *
39 * @remarks
40 *  None
41 *
42 *******************************************************************************
43 */
44 
45 #include <stdio.h>
46 #include <string.h>
47 #include "iv_datatypedef.h"
48 #include "iv.h"
49 #include "impeg2_buf_mgr.h"
50 #include "impeg2_disp_mgr.h"
51 #include "impeg2_defs.h"
52 #include "impeg2_platform_macros.h"
53 
54 #include "impeg2_inter_pred.h"
55 #include "impeg2_globals.h"
56 #include "impeg2_macros.h"
57 #include "impeg2_idct.h"
58 
59 /*******************************************************************************
60 *  Function Name   : impeg2_copy_mb
61 *
62 *  Description     : copies 3 components to the frame from mc_buf
63 *
64 *  Arguments       :
65 *  src_buf         : Source Buffer
66 *  dst_buf         : Destination Buffer
67 *  src_offset_x    : X offset for source
68 *  src_offset_y    : Y offset for source
69 *  dst_offset_x    : X offset for destination
70 *  dst_offset_y    : Y offset for destination
71 *  src_wd          : Source Width
72 *  dst_wd          : destination Width
73 *  rows            : Number of rows
74 *  cols            : Number of columns
75 *
76 *  Values Returned : None
77 *******************************************************************************/
impeg2_copy_mb(yuv_buf_t * ps_src_buf,yuv_buf_t * ps_dst_buf,UWORD32 u4_src_wd,UWORD32 u4_dst_wd)78 void impeg2_copy_mb(yuv_buf_t *ps_src_buf,
79                     yuv_buf_t *ps_dst_buf,
80                     UWORD32 u4_src_wd,
81                     UWORD32 u4_dst_wd)
82 {
83     UWORD8 *pu1_src;
84     UWORD8 *pu1_dst;
85     UWORD32 i;
86     UWORD32 u4_rows = MB_SIZE;
87     UWORD32 u4_cols = MB_SIZE;
88 
89     /*******************************************************/
90     /* copy Y                                              */
91     /*******************************************************/
92     pu1_src = ps_src_buf->pu1_y;
93     pu1_dst = ps_dst_buf->pu1_y;
94     for(i = 0; i < u4_rows; i++)
95     {
96         memcpy(pu1_dst, pu1_src, u4_cols);
97         pu1_src += u4_src_wd;
98         pu1_dst += u4_dst_wd;
99     }
100 
101     u4_src_wd >>= 1;
102     u4_dst_wd >>= 1;
103     u4_rows >>= 1;
104     u4_cols >>= 1;
105 
106     /*******************************************************/
107     /* copy U                                              */
108     /*******************************************************/
109     pu1_src = ps_src_buf->pu1_u;
110     pu1_dst = ps_dst_buf->pu1_u;
111     for(i = 0; i < u4_rows; i++)
112     {
113         memcpy(pu1_dst, pu1_src, u4_cols);
114 
115         pu1_src += u4_src_wd;
116         pu1_dst += u4_dst_wd;
117     }
118     /*******************************************************/
119     /* copy V                                              */
120     /*******************************************************/
121     pu1_src = ps_src_buf->pu1_v;
122     pu1_dst = ps_dst_buf->pu1_v;
123     for(i = 0; i < u4_rows; i++)
124     {
125         memcpy(pu1_dst, pu1_src, u4_cols);
126 
127         pu1_src += u4_src_wd;
128         pu1_dst += u4_dst_wd;
129     }
130 
131 }
132 
133 /*****************************************************************************/
134 /*                                                                           */
135 /*  Function Name : impeg2_interpolate                                       */
136 /*                                                                           */
137 /*  Description   : averages the contents of buf_src1 and buf_src2 and stores*/
138 /*                  result in buf_dst                                        */
139 /*                                                                           */
140 /*  Inputs        : buf_src1 -  First Source                                 */
141 /*                  buf_src2 -  Second Source                                */
142 /*                                                                           */
143 /*  Globals       : None                                                     */
144 /*                                                                           */
145 /*  Processing    : Avg the values from two sources and store the result in  */
146 /*                  destination buffer                                       */
147 /*                                                                           */
148 /*  Outputs       : buf_dst  -  Avg of contents of buf_src1 and buf_src2     */
149 /*                                                                           */
150 /*  Returns       : None                                                     */
151 /*                                                                           */
152 /*  Issues        : Assumes that all 3 buffers are of same size              */
153 /*                                                                           */
154 /*  Revision History:                                                        */
155 /*                                                                           */
156 /*         DD MM YYYY   Author(s)       Changes                              */
157 /*         14 09 2005   Harish M        First Version                        */
158 /*         15 09 2010   Venkat          Added stride                         */
159 /*                                                                           */
160 /*****************************************************************************/
impeg2_interpolate(yuv_buf_t * ps_buf_src1,yuv_buf_t * ps_buf_src2,yuv_buf_t * ps_buf_dst,UWORD32 u4_stride)161 void impeg2_interpolate(yuv_buf_t *ps_buf_src1,
162                         yuv_buf_t *ps_buf_src2,
163                         yuv_buf_t *ps_buf_dst,
164                         UWORD32 u4_stride)
165 {
166 
167     UWORD32 i,j;
168     UWORD8 *pu1_src1,*pu1_src2,*pu1_dst;
169     pu1_src1 = ps_buf_src1->pu1_y;
170     pu1_src2 = ps_buf_src2->pu1_y;
171     pu1_dst  = ps_buf_dst->pu1_y;
172     for(i = MB_SIZE; i > 0; i--)
173     {
174         for(j = MB_SIZE; j > 0; j--)
175         {
176             *pu1_dst++ = ((*pu1_src1++) + (*pu1_src2++) + 1) >> 1;
177         }
178 
179         pu1_dst += u4_stride - MB_SIZE;
180 
181     }
182 
183     u4_stride >>= 1;
184 
185     pu1_src1 = ps_buf_src1->pu1_u;
186     pu1_src2 = ps_buf_src2->pu1_u;
187     pu1_dst  = ps_buf_dst->pu1_u;
188     for(i = MB_CHROMA_SIZE; i > 0 ; i--)
189     {
190         for(j = MB_CHROMA_SIZE; j > 0; j--)
191         {
192             *pu1_dst++ = ((*pu1_src1++) + (*pu1_src2++) + 1) >> 1;
193         }
194 
195         pu1_dst += u4_stride - MB_CHROMA_SIZE;
196     }
197 
198     pu1_src1 = ps_buf_src1->pu1_v;
199     pu1_src2 = ps_buf_src2->pu1_v;
200     pu1_dst  = ps_buf_dst->pu1_v;
201     for(i = MB_CHROMA_SIZE; i > 0 ; i--)
202     {
203         for(j = MB_CHROMA_SIZE; j > 0; j--)
204         {
205             *pu1_dst++ = ((*pu1_src1++) + (*pu1_src2++) + 1) >> 1;
206         }
207 
208         pu1_dst += u4_stride - MB_CHROMA_SIZE;
209     }
210 
211 }
212 
213 /*****************************************************************************/
214 /*                                                                           */
215 /*  Function Name : impeg2_mc_halfx_halfy_8x8()                                 */
216 /*                                                                           */
217 /*  Description   : Gets the buffer from (0.5,0.5) to (8.5,8.5)              */
218 /*                  and the above block of size 8 x 8 will be placed as a    */
219 /*                  block from the current position of out_buf               */
220 /*                                                                           */
221 /*  Inputs        : ref - Reference frame from which the block will be       */
222 /*                        block will be extracted.                           */
223 /*                  ref_wid - WIdth of reference frame                       */
224 /*                  out_wid - WIdth of the output frame                      */
225 /*                  blk_width  - width of the block                          */
226 /*                  blk_width  - height of the block                         */
227 /*                                                                           */
228 /*  Globals       : None                                                     */
229 /*                                                                           */
230 /*  Processing    : Point to the (0,0),(1,0),(0,1),(1,1) position in         */
231 /*                  the ref frame.Interpolate these four values to get the   */
232 /*                  value at(0.5,0.5).Repeat this to get an 8 x 8 block      */
233 /*                  using 9 x 9 block from reference frame                   */
234 /*                                                                           */
235 /*  Outputs       : out -  Output containing the extracted block             */
236 /*                                                                           */
237 /*  Returns       : None                                                     */
238 /*                                                                           */
239 /*  Issues        : None                                                     */
240 /*                                                                           */
241 /*  Revision History:                                                        */
242 /*                                                                           */
243 /*         DD MM YYYY   Author(s)       Changes                              */
244 /*         05 09 2005   Harish M        First Version                        */
245 /*                                                                           */
246 /*****************************************************************************/
impeg2_mc_halfx_halfy_8x8(UWORD8 * pu1_out,UWORD8 * pu1_ref,UWORD32 u4_ref_wid,UWORD32 u4_out_wid)247 void impeg2_mc_halfx_halfy_8x8(UWORD8 *pu1_out,
248                             UWORD8 *pu1_ref,
249                             UWORD32 u4_ref_wid,
250                             UWORD32 u4_out_wid)
251 {
252     UWORD8 *pu1_ref_p0,*pu1_ref_p1,*pu1_ref_p2,*pu1_ref_p3;
253     UWORD32 i,j;
254     /* P0-P3 are the pixels in the reference frame and Q is the value being */
255     /* estimated                                                            */
256     /*
257        P0 P1
258          Q
259        P2 P3
260     */
261 
262     pu1_ref_p0 = pu1_ref;
263     pu1_ref_p1 = pu1_ref + 1;
264     pu1_ref_p2 = pu1_ref + u4_ref_wid;
265     pu1_ref_p3 = pu1_ref + u4_ref_wid + 1;
266 
267     for(i = 0; i < BLK_SIZE; i++)
268     {
269         for(j = 0; j < BLK_SIZE; j++)
270         {
271             *pu1_out++ =   (( (*pu1_ref_p0++ )
272                         + (*pu1_ref_p1++ )
273                         + (*pu1_ref_p2++ )
274                         + (*pu1_ref_p3++ ) + 2 ) >> 2);
275         }
276         pu1_ref_p0 += u4_ref_wid - BLK_SIZE;
277         pu1_ref_p1 += u4_ref_wid - BLK_SIZE;
278         pu1_ref_p2 += u4_ref_wid - BLK_SIZE;
279         pu1_ref_p3 += u4_ref_wid - BLK_SIZE;
280 
281         pu1_out    += u4_out_wid - BLK_SIZE;
282     }
283     return;
284 }
285 
286 /*****************************************************************************/
287 /*                                                                           */
288 /*  Function Name : impeg2_mc_halfx_fully_8x8()                                 */
289 /*                                                                           */
290 /*  Description   : Gets the buffer from (0.5,0) to (8.5,8)                  */
291 /*                  and the above block of size 8 x 8 will be placed as a    */
292 /*                  block from the current position of out_buf               */
293 /*                                                                           */
294 /*  Inputs        : ref - Reference frame from which the block will be       */
295 /*                        block will be extracted.                           */
296 /*                  ref_wid - WIdth of reference frame                       */
297 /*                  out_wid - WIdth of the output frame                      */
298 /*                  blk_width  - width of the block                          */
299 /*                  blk_width  - height of the block                         */
300 /*                                                                           */
301 /*  Globals       : None                                                     */
302 /*                                                                           */
303 /*  Processing    : Point to the (0,0) and (1,0) position in the ref frame   */
304 /*                  Interpolate these two values to get the value at(0.5,0)  */
305 /*                  Repeat this to get an 8 x 8 block using 9 x 8 block from */
306 /*                  reference frame                                          */
307 /*                                                                           */
308 /*  Outputs       : out -  Output containing the extracted block             */
309 /*                                                                           */
310 /*  Returns       : None                                                     */
311 /*                                                                           */
312 /*  Issues        : None                                                     */
313 /*                                                                           */
314 /*  Revision History:                                                        */
315 /*                                                                           */
316 /*         DD MM YYYY   Author(s)       Changes                              */
317 /*         05 09 2005   Harish M        First Version                        */
318 /*                                                                           */
319 /*****************************************************************************/
impeg2_mc_halfx_fully_8x8(UWORD8 * pu1_out,UWORD8 * pu1_ref,UWORD32 u4_ref_wid,UWORD32 u4_out_wid)320 void impeg2_mc_halfx_fully_8x8(UWORD8 *pu1_out,
321                             UWORD8 *pu1_ref,
322                             UWORD32 u4_ref_wid,
323                             UWORD32 u4_out_wid)
324 {
325     UWORD8 *pu1_ref_p0, *pu1_ref_p1;
326     UWORD32 i,j;
327 
328     /* P0-P3 are the pixels in the reference frame and Q is the value being */
329     /* estimated                                                            */
330     /*
331        P0 Q P1
332     */
333 
334     pu1_ref_p0 = pu1_ref;
335     pu1_ref_p1 = pu1_ref + 1;
336 
337     for(i = 0; i < BLK_SIZE; i++)
338     {
339         for(j = 0; j < BLK_SIZE; j++)
340         {
341             *pu1_out++ =   ((( *pu1_ref_p0++ )
342                         + (*pu1_ref_p1++) + 1 ) >> 1);
343         }
344         pu1_ref_p0 += u4_ref_wid - BLK_SIZE;
345         pu1_ref_p1 += u4_ref_wid - BLK_SIZE;
346 
347         pu1_out    += u4_out_wid - BLK_SIZE;
348     }
349     return;
350 }
351 
352 /*****************************************************************************/
353 /*                                                                           */
354 /*  Function Name : impeg2_mc_fullx_halfy_8x8()                                 */
355 /*                                                                           */
356 /*  Description   : Gets the buffer from (0,0.5) to (8,8.5)                  */
357 /*                  and the above block of size 8 x 8 will be placed as a    */
358 /*                  block from the current position of out_buf               */
359 /*                                                                           */
360 /*  Inputs        : ref - Reference frame from which the block will be       */
361 /*                        block will be extracted.                           */
362 /*                  ref_wid - WIdth of reference frame                       */
363 /*                  out_wid - WIdth of the output frame                      */
364 /*                  blk_width  - width of the block                          */
365 /*                  blk_width  - height of the block                         */
366 /*                                                                           */
367 /*  Globals       : None                                                     */
368 /*                                                                           */
369 /*  Processing    : Point to the (0,0) and (0,1)   position in the ref frame */
370 /*                  Interpolate these two values to get the value at(0,0.5)  */
371 /*                  Repeat this to get an 8 x 8 block using 8 x 9 block from */
372 /*                  reference frame                                          */
373 /*                                                                           */
374 /*  Outputs       : out -  Output containing the extracted block             */
375 /*                                                                           */
376 /*  Returns       : None                                                     */
377 /*                                                                           */
378 /*  Issues        : None                                                     */
379 /*                                                                           */
380 /*  Revision History:                                                        */
381 /*                                                                           */
382 /*         DD MM YYYY   Author(s)       Changes                              */
383 /*         05 09 2005   Harish M        First Version                        */
384 /*                                                                           */
385 /*****************************************************************************/
impeg2_mc_fullx_halfy_8x8(UWORD8 * pu1_out,UWORD8 * pu1_ref,UWORD32 u4_ref_wid,UWORD32 u4_out_wid)386 void impeg2_mc_fullx_halfy_8x8(UWORD8 *pu1_out,
387                             UWORD8 *pu1_ref,
388                             UWORD32 u4_ref_wid,
389                             UWORD32 u4_out_wid)
390 {
391 
392     UWORD8 *pu1_ref_p0, *pu1_ref_p1;
393     UWORD32 i,j;
394     /* P0-P3 are the pixels in the reference frame and Q is the value being */
395     /* estimated                                                            */
396     /*
397        P0
398         x
399        P1
400     */
401     pu1_ref_p0 = pu1_ref;
402     pu1_ref_p1 = pu1_ref + u4_ref_wid;
403 
404     for(i = 0; i < BLK_SIZE; i++)
405     {
406         for(j = 0; j < BLK_SIZE; j++)
407         {
408             *pu1_out++ =   ((( *pu1_ref_p0++)
409                         + (*pu1_ref_p1++) + 1 ) >> 1);
410         }
411         pu1_ref_p0 += u4_ref_wid - BLK_SIZE;
412         pu1_ref_p1 += u4_ref_wid - BLK_SIZE;
413 
414         pu1_out    += u4_out_wid - BLK_SIZE;
415     }
416 
417     return;
418 }
419 
420 /*****************************************************************************/
421 /*                                                                           */
422 /*  Function Name : impeg2_mc_fullx_fully_8x8()                                 */
423 /*                                                                           */
424 /*  Description   : Gets the buffer from (x,y) to (x+8,y+8)                  */
425 /*                  and the above block of size 8 x 8 will be placed as a    */
426 /*                  block from the current position of out_buf               */
427 /*                                                                           */
428 /*  Inputs        : ref - Reference frame from which the block will be       */
429 /*                        block will be extracted.                           */
430 /*                  ref_wid - WIdth of reference frame                       */
431 /*                  out_wid - WIdth of the output frame                      */
432 /*                  blk_width  - width of the block                          */
433 /*                  blk_width  - height of the block                         */
434 /*                                                                           */
435 /*  Globals       : None                                                     */
436 /*                                                                           */
437 /*  Processing    : Point to the (0,0) position in the ref frame             */
438 /*                  Get an 8 x 8 block from reference frame                  */
439 /*                                                                           */
440 /*  Outputs       : out -  Output containing the extracted block             */
441 /*                                                                           */
442 /*  Returns       : None                                                     */
443 /*                                                                           */
444 /*  Issues        : None                                                     */
445 /*                                                                           */
446 /*  Revision History:                                                        */
447 /*                                                                           */
448 /*         DD MM YYYY   Author(s)       Changes                              */
449 /*         05 09 2005   Harish M        First Version                        */
450 /*                                                                           */
451 /*****************************************************************************/
impeg2_mc_fullx_fully_8x8(UWORD8 * pu1_out,UWORD8 * pu1_ref,UWORD32 u4_ref_wid,UWORD32 u4_out_wid)452 void impeg2_mc_fullx_fully_8x8(UWORD8 *pu1_out,
453                             UWORD8 *pu1_ref,
454                             UWORD32 u4_ref_wid,
455                             UWORD32 u4_out_wid)
456 {
457 
458     UWORD32 i;
459 
460     for(i = 0; i < BLK_SIZE; i++)
461     {
462         memcpy(pu1_out, pu1_ref, BLK_SIZE);
463         pu1_ref += u4_ref_wid;
464         pu1_out += u4_out_wid;
465     }
466     return;
467 }
468