• MTK平台拍照录像如何实现Mirror效果


    (1)如何添加Mirror的Vendor Tag以及App如何调用

    可参考如下文章进行自定义Vendor Tag添加MTK Camera自定义Vendor Tag

    (2)前摄对预览,拍照,录像,缩列图进行Mirror处理

    可参考如下文章初步了解哪些地方可以进行Mirror 和 Flip处理Mtk Camera 对预览和拍照做Flip + Mirror

    (A)预览的Mirror效果

    前摄预览的Mirror效果是Google在Framework自行添加的,无需自行添加,具体可参考上面的文章。

    (B)拍照的Mirror效果

    //vendor/mediatek/proprietary/hardware/mtkcam3/pipeline/policy/request/CaptureStreamUpdaterPolicy.cpp
    
    static auto createRotationStreamInfoLocked_Main_YUV(
        RequestOutputParams& out __unused,
        RequestInputParams const& in __unused
    ) -> int
    {
        auto const pMetadata    = in.pRequest_AppControl;
        auto const pCfgMainYUV  = *(in.pConfiguration_HalImage_Jpeg_YUV);
        if ( CC_UNLIKELY( ! pMetadata || ! pCfgMainYUV.get() ) ) {
            MY_LOGE("invlaid input params");
            return NO_INIT;
        }
    
        IMetadata::IEntry const& entryJpegOrientation = pMetadata->entryFor(MTK_JPEG_ORIENTATION);
        if  ( entryJpegOrientation.isEmpty() ) {
            MY_LOGW("No tag: MTK_JPEG_ORIENTATION");
            return -EINVAL;
        }
    
        int32_t jpegFlip = 0;
        //jpegFlip:Jpeg的Flip效果
        IMetadata::IEntry const& entryJpegFlip = pMetadata->entryFor(MTK_CONTROL_CAPTURE_JPEG_FLIP_MODE);
        if (entryJpegFlip.isEmpty()) {
            MY_LOGD("No tag: MTK_CONTROL_CAPTURE_JPEG_FLIP_MODE");
        } else {
            jpegFlip = entryJpegFlip.itemAt(0, Type2Type<MINT32>());
        }
    
        int32_t jpegFlipProp = ::property_get_int32("vendor.debug.camera.Jpeg.flip", 0);
    
        int32_t const jpegOrientation = (in.isSupportJpegPack) ? 0 :
                                        entryJpegOrientation.itemAt(0, Type2Type<MINT32>());
        uint32_t      reqTransform   = 0;
    
        if (jpegFlip || jpegFlipProp) {
            if ( 0==jpegOrientation )
                reqTransform = eTransform_FLIP_H;
            else if ( 90==jpegOrientation )
                reqTransform = eTransform_ROT_90 | eTransform_FLIP_V;
            else if ( 180==jpegOrientation )
                reqTransform = eTransform_FLIP_V;
            else if ( 270==jpegOrientation )
                reqTransform = eTransform_ROT_90 | eTransform_FLIP_H;
            else
                MY_LOGW("Invalid Jpeg Orientation value: %d", jpegOrientation);
        } else {
            if ( 0==jpegOrientation )
                reqTransform = 0;
            else if ( 90==jpegOrientation )
                reqTransform = eTransform_ROT_90;
            else if ( 180==jpegOrientation )
                reqTransform = eTransform_ROT_180;
            else if ( 270==jpegOrientation )
                reqTransform = eTransform_ROT_270;
            else
                MY_LOGW("Invalid Jpeg Orientation value: %d", jpegOrientation);
        }
    	//...
    }
    
    • 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

    (C)缩列图的Mirror效果

    (a)普通的缩列图

    //vendor/mediatek/proprietary/hardware/mtkcam3/pipeline/hwnode/JpegNode/v2.0/JpegNode.cpp
    
    MVOID
    JpegNodeImp::
    encodeThumbnailJpeg(
        sp<encode_frame>& pEncodeFrame)
    {
        {
            // set thread naming
            pthread_setname_np(pthread_self(), THUMBTHREAD_NAME);
        }
        MSize thumbsize = pEncodeFrame->mParams.size_thumbnail;
        MUINT32 transform = (pEncodeFrame->mpYUV_MainStreamInfo.get()) ? pEncodeFrame->mpYUV_MainStreamInfo->getTransform() : 0;
        // do encode
        {
            my_encode_params params;
            params.frameNo = pEncodeFrame->mpFrame->getFrameNo();
            params.requestNo = pEncodeFrame->mpFrame->getRequestNo();
            params.pSrc = pEncodeFrame->mpYUV_Thumbnail.get();
            params.pDst = pEncodeFrame->mpJpeg_Thumbnail.get();
    
    		//pEncodeFrame->mParams.flipMode : 普通缩列图的Flip
            if (pEncodeFrame->mParams.flipMode || info.mFlip) {
                if( pEncodeFrame->mParams.orientation == 90 && transform & eTransform_ROT_90)
                {
                    params.transform = eTransform_ROT_90 | eTransform_FLIP_V;
                    std::swap(thumbsize.w, thumbsize.h);
                } else if (pEncodeFrame->mParams.orientation == 180 && transform & eTransform_ROT_180)
                {
                    params.transform = eTransform_FLIP_V;
                } else if (pEncodeFrame->mParams.orientation == 270 && transform & eTransform_ROT_270)
                {
                    params.transform = eTransform_ROT_90 | eTransform_FLIP_H;
                    std::swap(thumbsize.w, thumbsize.h);
                } else
                {
                    params.transform = eTransform_FLIP_H;
                }
    
    #if MTKCAM_EARLY_FLIP_SUPPORT == 1
                // has flipped in P2A, need to un-flip
                auto doUnflip= [&](MUINT32& trans, MINT32 dvOri) -> MVOID {
                    if (dvOri == 270) {
                        MY_LOGD("dvOri %d, Capture vertical", dvOri);
                        trans |= eTransform_FLIP_V;
                    } else if (dvOri == 90) {
                        MY_LOGD("dvOri %d, Capture vertical", dvOri);
                        trans &= ~eTransform_FLIP_V;
                    } else if (dvOri == 180) {
                        MY_LOGD("dvOri %d, Capture horizontal",dvOri);
                        trans |= eTransform_FLIP_H;
                    } else if (dvOri == 0) {
                        MY_LOGD("dvOri %d, Capture horizontal",dvOri);
                        trans &= ~eTransform_FLIP_H;
                    }
                };
                if (pEncodeFrame->mParams.isFlipped) {
                    MY_LOGD("before trans 0x%" PRIx64, params.transform);
                    doUnflip(params.transform, pEncodeFrame->mParams.orientation);
                    MY_LOGD("after trans 0x%" PRIx64, params.transform);
                }
    #endif
            } else {
                if( pEncodeFrame->mParams.orientation == 90 && transform & eTransform_ROT_90)
                {
                    params.transform = eTransform_ROT_90;
                    std::swap(thumbsize.w, thumbsize.h);
                } else if (pEncodeFrame->mParams.orientation == 180 && transform & eTransform_ROT_180)
                {
                    params.transform = eTransform_ROT_180;
                } else if (pEncodeFrame->mParams.orientation == 270 && transform & eTransform_ROT_270)
                {
                    params.transform = eTransform_ROT_270;
                    std::swap(thumbsize.w, thumbsize.h);
                } else
                {
                    params.transform = 0;
                }
            }
    
            params.crop =
                calCropAspect(pEncodeFrame->mpYUV_Thumbnail->getImgSize(), thumbsize);
            params.isSOI = 1;
            params.quality = pEncodeFrame->mParams.quality_thumbnail;
            params.codecType = NSSImager::JPEGENC_SW;
            params.bsOffset = pEncodeFrame->exif.getStdExifSize();
            //
            MINT32 quality = params.quality;
    
    		//...
    }
    
    • 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

    (b)postview方式

    由于postview方式是通过在Preview预览中来获取buffer的,所以可以参考如下FAQ修改Postview Flip

    相当于在提交Preview的request时将其添加Mirror能力。

    //vendor/mediatek/proprietary/hardware/mtkcam3/pipeline/model/session/PipelineModelSessionBasic.cpp
    
    auto
    ThisNamespace::
    submitOneRequest(
        std::shared_ptr<ParsedAppRequest>const& request __unused
    ) -> int
    {
        CAM_TRACE_CALL();
    
        auto const requestNo = request->requestNo;
    
        CAM_ULOG_ENTER(MOD_DEFAULT_PIPELINE_MODEL, REQ_APP_REQUEST, requestNo);
    
        // On this function, use this local variable to serve the request.
        auto pConfigInfo2 = getCurrentConfigInfo2();
    
        // Evaluate a result for a request.
        auto pReqOutputParams = std::make_shared<pipelinesetting::RequestOutputParams>();
        MY_LOGF_IF(pReqOutputParams==nullptr, "[requestNo:%u] Fail on make_shared", requestNo);
    
        RETURN_ERROR_IF_NOT_OK( onRequest_EvaluateRequest(*pReqOutputParams, request, pConfigInfo2),
                "[requestNo:%u] onRequest_EvaluateRequest", requestNo );
    
        // pConfigInfo2 could change after this call.
        RETURN_ERROR_IF_NOT_OK( onRequest_Reconfiguration(pConfigInfo2, *pReqOutputParams, request),
                "[requestNo:%u] onRequest_Reconfiguration", requestNo );
    
        RETURN_ERROR_IF_NOT_OK( onRequest_ProcessEvaluatedFrame(pReqOutputParams, request, pConfigInfo2),
                "[requestNo:%u] onRequest_ProcessEvaluatedFrame", requestNo );
    
        RETURN_ERROR_IF_NOT_OK( onRequest_Ending(*pReqOutputParams),
                "[requestNo:%u] onRequest_Ending", requestNo );
    
        return OK;
    }
    
    • 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

    (D) Recording + Vss的Mirror效果

    可先参考MTK平台的FAQRecording + Vss Flip

    可大致参考如下修改:

    //vendor/mediatek/proprietary/hardware/mtkcam3/pipeline/model/session/PipelineModelSessionBase.cpp
    
    auto
    PipelineModelSessionBase::
    submitRequest(
        std::vector<std::shared_ptr<UserRequestParams>>const& requests,
        uint32_t& numRequestProcessed
    ) -> int
    {
    	//...
    
    	//Submit ParsedAppRequest one by one
        for (size_t i = 0; i < reqs.size(); i++, numRequestProcessed++) {
        
            // add start
            int SensorID = mStaticInfo.pPipelineStaticInfo->sensorId[i];
            if(SensorID == 1){
                auto const& pAppControl = reqs[i]->pAppMetaControlStreamBuffer;
                IMetadata* pMetadata = pAppControl->tryReadLock(LOG_TAG);
                if ( CC_UNLIKELY( ! pMetadata ) ) {
                    MY_LOGE("bad metadata(%p) SBuffer(%p)", pMetadata, pAppControl.get() );
                    pAppControl->unlock(LOG_TAG, pMetadata);
                            return -EINVAL;
                }
                MINT32 videoFlip = 0;
                int32_t videoOrientation = 90;
                
                //这里进行读取videoFlip
                IMetadata::getEntry(pMetadata, MTK_CONTROL_CAPTURE_JPEG_FLIP_MODE, videoFlip);
                IMetadata::getEntry(pMetadata, MTK_STREAMING_FEATURE_XAPI_ROTATION, videoOrientation);
                pAppControl->unlock(LOG_TAG, pMetadata);
                MY_LOGD("%s:videoFlip = %d videoOrientation = %d\n",__FUNCTION__,videoFlip,videoOrientation);
                auto OpRequest_AppImageStreamInfo = reqs[i]->pParsedAppImageStreamInfo.get();
                for (auto & it : OpRequest_AppImageStreamInfo->vAppImage_Output_Proc) {
                    if (it.second->getUsageForConsumer() & GRALLOC_USAGE_HW_VIDEO_ENCODER ){
                        uint32_t reqTransform = 0;
                        if (videoFlip) {
                                if ( 0 == videoOrientation ) {
                                    reqTransform = eTransform_FLIP_H;
                                }else if ( 90 == videoOrientation ) {
                                    reqTransform = eTransform_FLIP_V;
                                }else if ( 180 == videoOrientation ) {
                                    reqTransform = eTransform_FLIP_H;
                                }else if ( 270 == videoOrientation ) {
                                    reqTransform = eTransform_FLIP_V;}
                                }else {
                                    MY_LOGW("Invalid videoOrientation value: %d", videoOrientation);
                                }
                        MY_LOGD("set video flip reqTransform: %d", reqTransform);
                        it.second->setTransform(reqTransform);
                    }
                }
            }
            // add end
            RETURN_ERROR_IF_NOT_OK( submitOneRequest(reqs[i]),
                "submitOneRequest fail on requestNo:%u - %u/%zu requests submitted sucessfully",
                reqs[i]->requestNo, numRequestProcessed, reqs.size() );
        }
    
        return OK;
    }
    
    • 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
  • 相关阅读:
    C语言入门(二)运算符和表达式
    HTML零基础入门教程完整版
    【重识云原生】第六章容器6.1.7.3节——cgroups数据结构剖析
    qml保姆级教程五:视图组件
    JavaScript面向对象学习深拷贝、浅拷贝(三)
    vue实现无感刷新token
    vue3+electron开发桌面应用,静态资源处理方式及路径问题总结
    简单了解JDBC相关操作
    AJAX(异步的 JavaScript 和 XML)
    [ vulhub漏洞复现篇 ] Django debug page XSS漏洞 CVE-2017-12794
  • 原文地址:https://blog.csdn.net/dongxianfei/article/details/126125744