summaryrefslogtreecommitdiffstats
path: root/libvideoeditor/vss/src/M4PTO3GPP_VideoPreProcessing.c
blob: 96a64981636f99dac703ac075bfa65a4008e306e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 * 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;
}