/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
******************************************************************************
* @file M4PTO3GPP_VideoPreProcessing.c
* @brief Picture to 3gpp Service video preprocessing management.
******************************************************************************
*/
/**
* OSAL Debug utilities */
#include "M4OSA_Debug.h"
/**
* OSAL Memory management */
#include "M4OSA_Memory.h"
/**
* Definition of the M4PTO3GPP internal context */
#include "M4PTO3GPP_InternalTypes.h"
/**
* Definition of the M4PTO3GPP errors */
#include "M4PTO3GPP_ErrorCodes.h"
/* If time increment is too low then we have an infinite alloc loop into M4ViEncCaptureFrame() */
/* Time increment should match 30 fps maximum */
#define M4PTO3GPP_MIN_TIME_INCREMENT 33.3333334
/**
******************************************************************************
* M4OSA_ERR M4PTO3GPP_applyVPP(M4VPP_Context pContext, M4VIFI_ImagePlane* pPlaneIn,
* M4VIFI_ImagePlane* pPlaneOut)
* @brief Call an external callback to get the picture to encode
* @note It is called by the video encoder
* @param pContext (IN) VPP context, which actually is the M4PTO3GPP internal context
* in our case
* @param pPlaneIn (IN) Contains the image
* @param pPlaneOut (IN/OUT) Pointer to an array of 3 planes that will contain the
* output YUV420 image read with the m_pPictureCallbackFct
* @return M4NO_ERROR: No error
* @return Any error returned by an underlaying module
******************************************************************************
*/
/******************************************************/
M4OSA_ERR M4PTO3GPP_applyVPP(M4VPP_Context pContext, M4VIFI_ImagePlane* pPlaneIn,
M4VIFI_ImagePlane* pPlaneOut)
/******************************************************/
{
M4OSA_ERR err;
M4OSA_Double mtDuration;
M4OSA_UInt32 i;
/*** NOTE ***/
/* It's OK to get pPlaneIn == M4OSA_NULL here */
/* since it has been given NULL in the pFctEncode() call. */
/* It's because we use the M4PTO3GPP internal context to */
/* transmit the encoder input data. */
/* The input data is the image read from the m_pPictureCallbackFct */
/**
* The VPP context is actually the M4PTO3GPP context! */
M4PTO3GPP_InternalContext *pC = (M4PTO3GPP_InternalContext*)(pContext);
/**
* Get the picture to encode */
if (M4OSA_FALSE == pC->m_bLastInternalCallBack)
{
err = pC->m_Params.pPictureCallbackFct(pC->m_Params.pPictureCallbackCtxt, pPlaneOut,
&mtDuration);
/* In case of error when getting YUV to encode (ex: error when decoding a JPEG) */
if((M4NO_ERROR != err) && (((M4OSA_UInt32)M4PTO3GPP_WAR_LAST_PICTURE) != err))
{
return err;
}
/**
* If end of encoding is asked by the size limitation system,
* we must end the encoding the same way that when it is asked by the
* picture callback (a.k.a. the integrator).
* Thus we simulate the LastPicture code return: */
if (M4OSA_TRUE == pC->m_IsLastPicture)
{
err = M4PTO3GPP_WAR_LAST_PICTURE;
}
if(((M4OSA_UInt32)M4PTO3GPP_WAR_LAST_PICTURE) == err)
{
pC->m_bLastInternalCallBack = M4OSA_TRUE; /* Toggle flag for the final call of the CB*/
pC->m_IsLastPicture = M4OSA_TRUE; /* To stop the encoder */
pC->pSavedPlane = pPlaneOut; /* Save the last YUV plane ptr */
pC->uiSavedDuration = (M4OSA_UInt32)mtDuration; /* Save the last duration */
}
}
else
{
/**< Not necessary here because the last frame duration is set to the-last-but-one by
the light writer */
/**< Only necessary for pC->m_mtNextCts below...*/
mtDuration = pC->uiSavedDuration;
/** Copy the last YUV plane into the current one
* (the last pic is splited due to the callback extra-call... */
for (i=0; i<3; i++)
{
memcpy((void *)pPlaneOut[i].pac_data,
(void *)pC->pSavedPlane[i].pac_data,
pPlaneOut[i].u_stride * pPlaneOut[i].u_height);
}
}
/* TimeIncrement should be 30 fps maximum */
if(mtDuration < M4PTO3GPP_MIN_TIME_INCREMENT)
{
mtDuration = M4PTO3GPP_MIN_TIME_INCREMENT;
}
pC->m_mtNextCts += mtDuration;
M4OSA_TRACE3_0("M4PTO3GPP_applyVPP: returning M4NO_ERROR");
return M4NO_ERROR;
}