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    M4PTO3GPP_VideoPreProcessing.c
19 * @brief   Picture to 3gpp Service video preprocessing management.
20 ******************************************************************************
21 */
22
23/**
24 *    OSAL Debug utilities */
25#include "M4OSA_Debug.h"
26
27/**
28 *    OSAL Memory management */
29#include "M4OSA_Memory.h"
30
31/**
32 *    Definition of the M4PTO3GPP internal context */
33#include "M4PTO3GPP_InternalTypes.h"
34
35/**
36 *    Definition of the M4PTO3GPP errors */
37#include "M4PTO3GPP_ErrorCodes.h"
38
39/* If time increment is too low then we have an infinite alloc loop into M4ViEncCaptureFrame() */
40/* Time increment should match 30 fps maximum */
41#define M4PTO3GPP_MIN_TIME_INCREMENT 33.3333334
42
43
44/**
45 ******************************************************************************
46 * M4OSA_ERR M4PTO3GPP_applyVPP(M4VPP_Context pContext, M4VIFI_ImagePlane* pPlaneIn,
47 *                                 M4VIFI_ImagePlane* pPlaneOut)
48 * @brief    Call an external callback to get the picture to encode
49 * @note    It is called by the video encoder
50 * @param    pContext    (IN) VPP context, which actually is the M4PTO3GPP internal context
51 *                            in our case
52 * @param    pPlaneIn    (IN) Contains the image
53 * @param    pPlaneOut    (IN/OUT) Pointer to an array of 3 planes that will contain the
54 *                        output YUV420 image read with the m_pPictureCallbackFct
55 * @return    M4NO_ERROR:    No error
56 * @return    Any error returned by an underlaying module
57 ******************************************************************************
58 */
59/******************************************************/
60M4OSA_ERR M4PTO3GPP_applyVPP(M4VPP_Context pContext, M4VIFI_ImagePlane* pPlaneIn,
61                             M4VIFI_ImagePlane* pPlaneOut)
62/******************************************************/
63{
64    M4OSA_ERR    err;
65    M4OSA_Double mtDuration;
66    M4OSA_UInt32 i;
67
68    /*** NOTE ***/
69    /* It's OK to get pPlaneIn == M4OSA_NULL here                        */
70    /* since it has been given NULL in the pFctEncode() call.            */
71    /* It's because we use the M4PTO3GPP internal context to            */
72    /* transmit the encoder input data.                                    */
73    /* The input data is the image read from the m_pPictureCallbackFct    */
74
75    /**
76     *    The VPP context is actually the M4PTO3GPP context! */
77    M4PTO3GPP_InternalContext *pC = (M4PTO3GPP_InternalContext*)(pContext);
78
79    /**
80    *  Get the picture to encode */
81    if (M4OSA_FALSE == pC->m_bLastInternalCallBack)
82    {
83        err = pC->m_Params.pPictureCallbackFct(pC->m_Params.pPictureCallbackCtxt, pPlaneOut,
84             &mtDuration);
85
86        /* In case of error when getting YUV to encode (ex: error when decoding a JPEG) */
87        if((M4NO_ERROR != err) && (((M4OSA_UInt32)M4PTO3GPP_WAR_LAST_PICTURE) != err))
88        {
89            return err;
90        }
91
92        /**
93         * If end of encoding is asked by the size limitation system,
94         * we must end the encoding the same way that when it is asked by the
95         * picture callback (a.k.a. the integrator).
96         * Thus we simulate the LastPicture code return: */
97        if (M4OSA_TRUE == pC->m_IsLastPicture)
98        {
99            err = M4PTO3GPP_WAR_LAST_PICTURE;
100        }
101
102        if(((M4OSA_UInt32)M4PTO3GPP_WAR_LAST_PICTURE) == err)
103        {
104            pC->m_bLastInternalCallBack = M4OSA_TRUE; /* Toggle flag for the final call of the CB*/
105            pC->m_IsLastPicture         = M4OSA_TRUE; /* To stop the encoder */
106            pC->pSavedPlane             = pPlaneOut;  /* Save the last YUV plane ptr */
107            pC->uiSavedDuration         = (M4OSA_UInt32)mtDuration; /* Save the last duration */
108        }
109    }
110    else
111    {
112        /**< Not necessary here because the last frame duration is set to the-last-but-one by
113                the light writer */
114        /**< Only necessary for pC->m_mtNextCts below...*/
115        mtDuration = pC->uiSavedDuration;
116
117
118        /** Copy the last YUV plane into the current one
119         * (the last pic is splited due to the callback extra-call... */
120        for (i=0; i<3; i++)
121        {
122            memcpy((void *)pPlaneOut[i].pac_data,
123                 (void *)pC->pSavedPlane[i].pac_data,
124                     pPlaneOut[i].u_stride * pPlaneOut[i].u_height);
125        }
126    }
127
128    /* TimeIncrement should be 30 fps maximum */
129    if(mtDuration < M4PTO3GPP_MIN_TIME_INCREMENT)
130    {
131        mtDuration = M4PTO3GPP_MIN_TIME_INCREMENT;
132    }
133
134    pC->m_mtNextCts += mtDuration;
135
136    M4OSA_TRACE3_0("M4PTO3GPP_applyVPP: returning M4NO_ERROR");
137    return M4NO_ERROR;
138}
139
140