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*******************************************************************************/
78void 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/*****************************************************************************/
161void 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/*****************************************************************************/
247void 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/*****************************************************************************/
320void 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/*****************************************************************************/
386void 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/*****************************************************************************/
452void 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