Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e9eec0e0 authored by Rajneesh Chowdury's avatar Rajneesh Chowdury
Browse files

Fix for 5156702 Rotate video output for thumbnails and export

This is part of a multi project submit.
This is the native engine part.

Change-Id: Icde922194a123a90544942caa12430fc3c4ef10e
parent dac2f050
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -825,6 +825,26 @@ M4OSA_ERR VideoEditorPreviewController::renderPreviewFrame(

    pixelArray = NULL;

    // Apply rotation if required
    if (pFrameStr->videoRotationDegree != 0) {
        err = applyVideoRotation((M4OSA_Void *)pFrameStr->pBuffer,
                  pFrameStr->uiFrameWidth, pFrameStr->uiFrameHeight,
                  pFrameStr->videoRotationDegree);
        if (M4NO_ERROR != err) {
            LOGE("renderPreviewFrame: cannot rotate video, err 0x%x", (unsigned int)err);
            delete mTarget;
            mTarget = NULL;
            return err;
        } else {
           // Video rotation done.
           // Swap width and height if 90 or 270 degrees
           if (pFrameStr->videoRotationDegree != 180) {
               int32_t temp = pFrameStr->uiFrameWidth;
               pFrameStr->uiFrameWidth = pFrameStr->uiFrameHeight;
               pFrameStr->uiFrameHeight = temp;
           }
        }
    }
    // Postprocessing (apply video effect)
    if(pFrameStr->bApplyEffect == M4OSA_TRUE) {

+211 −0
Original line number Diff line number Diff line
@@ -3672,3 +3672,214 @@ android::status_t getVideoSizeByResolution(

    return android::OK;
}

M4VIFI_UInt8 M4VIFI_Rotate90LeftYUV420toYUV420(void* pUserData,
    M4VIFI_ImagePlane *pPlaneIn, M4VIFI_ImagePlane *pPlaneOut) {

    M4VIFI_Int32 plane_number;
    M4VIFI_UInt32 i,j, u_stride;
    M4VIFI_UInt8 *p_buf_src, *p_buf_dest;

    /**< Loop on Y,U and V planes */
    for (plane_number = 0; plane_number < 3; plane_number++) {
        /**< Get adresses of first valid pixel in input and output buffer */
        /**< As we have a -90° rotation, first needed pixel is the upper-right one */
        p_buf_src =
            &(pPlaneIn[plane_number].pac_data[pPlaneIn[plane_number].u_topleft]) +
             pPlaneOut[plane_number].u_height - 1 ;
        p_buf_dest =
            &(pPlaneOut[plane_number].pac_data[pPlaneOut[plane_number].u_topleft]);
        u_stride = pPlaneIn[plane_number].u_stride;
        /**< Loop on output rows */
        for (i = 0; i < pPlaneOut[plane_number].u_height; i++) {
            /**< Loop on all output pixels in a row */
            for (j = 0; j < pPlaneOut[plane_number].u_width; j++) {
                *p_buf_dest++= *p_buf_src;
                p_buf_src += u_stride;  /**< Go to the next row */
            }

            /**< Go on next row of the output frame */
            p_buf_dest +=
                pPlaneOut[plane_number].u_stride - pPlaneOut[plane_number].u_width;
            /**< Go to next pixel in the last row of the input frame*/
            p_buf_src -=
                pPlaneIn[plane_number].u_stride * pPlaneOut[plane_number].u_width + 1 ;
        }
    }

    return M4VIFI_OK;
}

M4VIFI_UInt8 M4VIFI_Rotate90RightYUV420toYUV420(void* pUserData,
    M4VIFI_ImagePlane *pPlaneIn, M4VIFI_ImagePlane *pPlaneOut) {

    M4VIFI_Int32 plane_number;
    M4VIFI_UInt32 i,j, u_stride;
    M4VIFI_UInt8 *p_buf_src, *p_buf_dest;

    /**< Loop on Y,U and V planes */
    for (plane_number = 0; plane_number < 3; plane_number++) {
        /**< Get adresses of first valid pixel in input and output buffer */
        /**< As we have a +90° rotation, first needed pixel is the left-down one */
        p_buf_src =
            &(pPlaneIn[plane_number].pac_data[pPlaneIn[plane_number].u_topleft]) +
             (pPlaneIn[plane_number].u_stride * (pPlaneOut[plane_number].u_width - 1));
        p_buf_dest =
            &(pPlaneOut[plane_number].pac_data[pPlaneOut[plane_number].u_topleft]);
        u_stride = pPlaneIn[plane_number].u_stride;
        /**< Loop on output rows */
        for (i = 0; i < pPlaneOut[plane_number].u_height; i++) {
            /**< Loop on all output pixels in a row */
            for (j = 0; j < pPlaneOut[plane_number].u_width; j++) {
                *p_buf_dest++= *p_buf_src;
                p_buf_src -= u_stride;  /**< Go to the previous row */
            }

            /**< Go on next row of the output frame */
            p_buf_dest +=
                pPlaneOut[plane_number].u_stride - pPlaneOut[plane_number].u_width;
            /**< Go to next pixel in the last row of the input frame*/
            p_buf_src +=
                pPlaneIn[plane_number].u_stride * pPlaneOut[plane_number].u_width +1 ;
        }
    }

    return M4VIFI_OK;
}

M4VIFI_UInt8 M4VIFI_Rotate180YUV420toYUV420(void* pUserData,
    M4VIFI_ImagePlane *pPlaneIn, M4VIFI_ImagePlane *pPlaneOut) {
    M4VIFI_Int32 plane_number;
    M4VIFI_UInt32 i,j;
    M4VIFI_UInt8 *p_buf_src, *p_buf_dest, temp_pix1;

    /**< Loop on Y,U and V planes */
    for (plane_number = 0; plane_number < 3; plane_number++) {
        /**< Get adresses of first valid pixel in input and output buffer */
        p_buf_src =
            &(pPlaneIn[plane_number].pac_data[pPlaneIn[plane_number].u_topleft]);
        p_buf_dest =
            &(pPlaneOut[plane_number].pac_data[pPlaneOut[plane_number].u_topleft]);

        /**< If pPlaneIn = pPlaneOut, the algorithm will be different */
        if (p_buf_src == p_buf_dest) {
            /**< Get Address of last pixel in the last row of the frame */
            p_buf_dest +=
                pPlaneOut[plane_number].u_stride*(pPlaneOut[plane_number].u_height-1) +
                 pPlaneOut[plane_number].u_width - 1;

            /**< We loop (height/2) times on the rows.
             * In case u_height is odd, the row at the middle of the frame
             * has to be processed as must be mirrored */
            for (i = 0; i < ((pPlaneOut[plane_number].u_height)>>1); i++) {
                for (j = 0; j < pPlaneOut[plane_number].u_width; j++) {
                    temp_pix1= *p_buf_dest;
                    *p_buf_dest--= *p_buf_src;
                    *p_buf_src++ = temp_pix1;
                }
                /**< Go on next row in top of frame */
                p_buf_src +=
                    pPlaneOut[plane_number].u_stride - pPlaneOut[plane_number].u_width;
                /**< Go to the last pixel in previous row in bottom of frame*/
                p_buf_dest -=
                    pPlaneOut[plane_number].u_stride - pPlaneOut[plane_number].u_width;
            }

            /**< Mirror middle row in case height is odd */
            if ((pPlaneOut[plane_number].u_height%2)!= 0) {
                p_buf_src =
                    &(pPlaneOut[plane_number].pac_data[pPlaneIn[plane_number].u_topleft]);
                p_buf_src +=
                    pPlaneOut[plane_number].u_stride*(pPlaneOut[plane_number].u_height>>1);
                p_buf_dest =
                    p_buf_src + pPlaneOut[plane_number].u_width;

                /**< We loop u_width/2 times on this row.
                 *  In case u_width is odd, the pixel at the middle of this row
                 * remains unchanged */
                for (j = 0; j < (pPlaneOut[plane_number].u_width>>1); j++) {
                    temp_pix1= *p_buf_dest;
                    *p_buf_dest--= *p_buf_src;
                    *p_buf_src++ = temp_pix1;
                }
            }
        } else {
            /**< Get Address of last pixel in the last row of the output frame */
            p_buf_dest +=
                pPlaneOut[plane_number].u_stride*(pPlaneOut[plane_number].u_height-1) +
                 pPlaneIn[plane_number].u_width - 1;

            /**< Loop on rows */
            for (i = 0; i < pPlaneOut[plane_number].u_height; i++) {
                for (j = 0; j < pPlaneOut[plane_number].u_width; j++) {
                    *p_buf_dest--= *p_buf_src++;
                }

                /**< Go on next row in top of input frame */
                p_buf_src +=
                    pPlaneIn[plane_number].u_stride - pPlaneOut[plane_number].u_width;
                /**< Go to last pixel of previous row in bottom of input frame*/
                p_buf_dest -=
                    pPlaneOut[plane_number].u_stride - pPlaneOut[plane_number].u_width;
            }
        }
    }

    return M4VIFI_OK;
}

M4OSA_ERR applyVideoRotation(M4OSA_Void* pBuffer, M4OSA_UInt32 width,
                             M4OSA_UInt32 height, M4OSA_UInt32 rotation) {

    M4OSA_ERR err = M4NO_ERROR;
    M4VIFI_ImagePlane planeIn[3], planeOut[3];

    if (pBuffer == M4OSA_NULL) {
        LOGE("applyVideoRotation: NULL input frame");
        return M4ERR_PARAMETER;
    }
    M4OSA_UInt8* outPtr = (M4OSA_UInt8 *)M4OSA_32bitAlignedMalloc(
     (width*height*1.5), M4VS, (M4OSA_Char*)("rotation out ptr"));
    if (outPtr == M4OSA_NULL) {
        return M4ERR_ALLOC;
    }

    // In plane
    prepareYUV420ImagePlane(planeIn, width,
        height, (M4VIFI_UInt8 *)pBuffer, width, height);

    // Out plane
    if (rotation != 180) {
        prepareYUV420ImagePlane(planeOut, height,
            width, outPtr, height, width);
    }

    switch(rotation) {
        case 90:
            M4VIFI_Rotate90RightYUV420toYUV420(M4OSA_NULL, planeIn, planeOut);
            memset(pBuffer, 0, (width*height*1.5));
            memcpy(pBuffer, (void *)outPtr, (width*height*1.5));
            break;

        case 180:
            // In plane rotation, so planeOut = planeIn
            M4VIFI_Rotate180YUV420toYUV420(M4OSA_NULL, planeIn, planeIn);
            break;

        case 270:
            M4VIFI_Rotate90LeftYUV420toYUV420(M4OSA_NULL, planeIn, planeOut);
            memset(pBuffer, 0, (width*height*1.5));
            memcpy(pBuffer, (void *)outPtr, (width*height*1.5));
            break;

        default:
            LOGE("invalid rotation param %d", (int)rotation);
            err = M4ERR_PARAMETER;
            break;
    }

    free((void *)outPtr);
    return err;

}
+11 −0
Original line number Diff line number Diff line
@@ -139,4 +139,15 @@ M4OSA_ERR applyEffectsAndRenderingMode(vePostProcessParams *params,
android::status_t getVideoSizeByResolution(M4VIDEOEDITING_VideoFrameSize resolution,
    uint32_t *pWidth, uint32_t *pHeight);

M4VIFI_UInt8 M4VIFI_Rotate90LeftYUV420toYUV420(void* pUserData,
    M4VIFI_ImagePlane *pPlaneIn, M4VIFI_ImagePlane *pPlaneOut);

M4VIFI_UInt8 M4VIFI_Rotate90RightYUV420toYUV420(void* pUserData,
    M4VIFI_ImagePlane *pPlaneIn, M4VIFI_ImagePlane *pPlaneOut);

M4VIFI_UInt8 M4VIFI_Rotate180YUV420toYUV420(void* pUserData,
    M4VIFI_ImagePlane *pPlaneIn, M4VIFI_ImagePlane *pPlaneOut);

M4OSA_ERR applyVideoRotation(M4OSA_Void* pBuffer,
    M4OSA_UInt32 width, M4OSA_UInt32 height, M4OSA_UInt32 rotation);
#endif // ANDROID_VE_TOOLS_H
+1 −0
Original line number Diff line number Diff line
@@ -118,6 +118,7 @@ typedef struct
    M4OSA_UInt32        m_videoHeight;            /**< Height of the video in the stream */
    M4OSA_Float            m_averageFrameRate;        /**< Average frame rate of the video
                                                            in the stream */
    M4OSA_Int32         videoRotationDegrees;        /**< Video rotation degree */
    M4OSA_UInt32        m_structSize;            /**< Size of the structure in bytes */
} M4_VideoStreamHandler;

+2 −0
Original line number Diff line number Diff line
@@ -323,6 +323,8 @@ typedef struct {
    M4OSA_UInt32                        uiClipAudioVolumePercentage;
    M4OSA_Bool                          bSetImageData;

    M4OSA_Int32     videoRotationDegrees;        /**< Video rotation degree */

} M4VIDEOEDITING_ClipProperties;


Loading