int ExynosMPP::processM2M(hwc_layer_1_t &layer, int dst_format, hwc_frect_t *sourceCrop)
#endif
{
    ALOGV("configuring gscaler %u for memory-to-memory", AVAILABLE_GSC_UNITS[mIndex]);

    alloc_device_t* alloc_device = mDisplay->mAllocDevice;
    private_handle_t *src_handle = private_handle_t::dynamicCast(layer.handle);
    buffer_handle_t dst_buf;
    private_handle_t *dst_handle;
    buffer_handle_t mid_buf;
    private_handle_t *mid_handle;
    int ret = 0;
    int dstAlign;
#ifdef USES_VIRTUAL_DISPLAY
    bool need_gsc_op_twice = false;
#endif

    exynos_mpp_img src_img, dst_img;
    memset(&src_img, 0, sizeof(src_img));
    memset(&dst_img, 0, sizeof(dst_img));
    exynos_mpp_img mid_img;
    memset(&mid_img, 0, sizeof(mid_img));

    hwc_frect_t sourceCropTemp;
    if (!sourceCrop)
        sourceCrop = &sourceCropTemp;

    setupSource(src_img, layer);
    src_img.mem_type = GSC_MEM_DMABUF;

#ifdef USES_VIRTUAL_DISPLAY
    need_gsc_op_twice = setupDoubleOperation(src_img, mid_img, layer) && isNeedBufferAlloc;
#else
    bool need_gsc_op_twice = setupDoubleOperation(src_img, mid_img, layer);
#endif

    setupM2MDestination(src_img, dst_img, dst_format, layer, sourceCrop);

#ifdef USES_VIRTUAL_DISPLAY
    if (!isNeedBufferAlloc) {
        dst_img.x = mDisplay->mHwc->mVirtualDisplayRect.left;
        dst_img.y = mDisplay->mHwc->mVirtualDisplayRect.top;
        dst_img.w = mDisplay->mHwc->mVirtualDisplayRect.width;
        dst_img.h = mDisplay->mHwc->mVirtualDisplayRect.height;
    }
#endif

    ALOGV("source configuration:");
    dumpMPPImage(src_img);

    bool reconfigure = isSrcConfigChanged(src_img, mSrcConfig) ||
            isDstConfigChanged(dst_img, mDstConfig);
    bool realloc = true;

#ifdef USES_VIRTUAL_DISPLAY
    if (isNeedBufferAlloc) {
#endif
    /* ext_only andn int_only changes */
    if (!need_gsc_op_twice && getDrmMode(src_handle->flags) == SECURE_DRM) {
        if (dst_img.drmMode != mDstConfig.drmMode)
            realloc = true;
        else
            realloc = false;
    }

    if (reconfigure && realloc) {
        if (reallocateBuffers(src_handle, dst_img, mid_img, need_gsc_op_twice) < 0)
            goto err_alloc;

        mCurrentBuf = 0;
        mLastGSCLayerHandle = 0;
    }

    if (!reconfigure && (mLastGSCLayerHandle == layer.handle)) {
        ALOGV("[USE] GSC_SKIP_DUPLICATE_FRAME_PROCESSING\n");
        if (layer.acquireFenceFd >= 0)
            close(layer.acquireFenceFd);

        layer.releaseFenceFd = -1;
        layer.acquireFenceFd = -1;
        mDstConfig.releaseFenceFd = -1;

        mCurrentBuf = (mCurrentBuf + NUM_GSC_DST_BUFS - 1) % NUM_GSC_DST_BUFS;
        if (mDstBufFence[mCurrentBuf] >= 0) {
            close (mDstBufFence[mCurrentBuf]);
            mDstBufFence[mCurrentBuf] = -1;
        }
        return 0;
    } else {
        mLastGSCLayerHandle = layer.handle;
    }
#ifdef USES_VIRTUAL_DISPLAY
    }
#endif

    layer.acquireFenceFd = -1;
    if (need_gsc_op_twice) {
        mid_img.acquireFenceFd = mMidBufFence[mCurrentBuf];
        mMidBufFence[mCurrentBuf] = -1;
        mid_buf = mMidBuffers[mCurrentBuf];
        mid_handle = private_handle_t::dynamicCast(mid_buf);

        mid_img.fw = mid_handle->stride;
        mid_img.fh = mid_handle->vstride;
        mid_img.yaddr = mid_handle->fd;
        if (isFormatYCrCb(mid_handle->format)) {
            mid_img.uaddr = mid_handle->fd2;
            mid_img.vaddr = mid_handle->fd1;
        } else {
            mid_img.uaddr = mid_handle->fd1;
            mid_img.vaddr = mid_handle->fd2;
        }
        //mid_img.acquireFenceFd = -1;

        ALOGV("mid configuration:");
        dumpMPPImage(mid_img);
    }

    dst_buf = mDstBuffers[mCurrentBuf];
    dst_handle = private_handle_t::dynamicCast(dst_buf);

    dst_img.fw = dst_handle->stride;
    dst_img.fh = dst_handle->vstride;
    dst_img.yaddr = dst_handle->fd;
    dst_img.uaddr = dst_handle->fd1;
    dst_img.vaddr = dst_handle->fd2;
    dst_img.acquireFenceFd = mDstBufFence[mCurrentBuf];
    mDstBufFence[mCurrentBuf] = -1;

    ALOGV("destination configuration:");
    dumpMPPImage(dst_img);

    if ((int)dst_img.w != WIDTH(layer.displayFrame))
        ALOGV("padding %u x %u output to %u x %u and cropping to {%7.1f,%7.1f,%7.1f,%7.1f}",
                WIDTH(layer.displayFrame), HEIGHT(layer.displayFrame),
                dst_img.w, dst_img.h, sourceCrop->left, sourceCrop->top,
                sourceCrop->right, sourceCrop->bottom);

    if (mGscHandle) {
        ALOGV("reusing open gscaler %u", AVAILABLE_GSC_UNITS[mIndex]);
    } else {
        ALOGV("opening gscaler %u", AVAILABLE_GSC_UNITS[mIndex]);
        mGscHandle = createMPP(
                AVAILABLE_GSC_UNITS[mIndex], GSC_M2M_MODE, GSC_DUMMY, true);
        if (!mGscHandle) {
            ALOGE("failed to create gscaler handle");
            ret = -1;
            goto err_alloc;
        }
    }

    if (!need_gsc_op_twice)
        memcpy(&mid_img, &dst_img, sizeof(exynos_mpp_img));

    /* src -> mid or src->dest */
    if (reconfigure || need_gsc_op_twice) {
        ret = stopMPP(mGscHandle);
        if (ret < 0) {
            ALOGE("failed to stop gscaler %u", mIndex);
            goto err_gsc_config;
        }

        ret = setCSCProperty(mGscHandle, 0, !mid_img.narrowRgb, 1);
        ret = configMPP(mGscHandle, &src_img, &mid_img);
        if (ret < 0) {
            ALOGE("failed to configure gscaler %u", mIndex);
            goto err_gsc_config;
        }
    }

    ret = runMPP(mGscHandle, &src_img, &mid_img);
    if (ret < 0) {
        ALOGE("failed to run gscaler %u", mIndex);
        goto err_gsc_config;
    }

    /* mid -> dst */
    if (need_gsc_op_twice) {
        ret = stopMPP(mGscHandle);
        if (ret < 0) {
            ALOGE("failed to stop gscaler %u", mIndex);
            goto err_gsc_config;
        }

        mid_img.acquireFenceFd = mid_img.releaseFenceFd;

        ret = setCSCProperty(mGscHandle, 0, !dst_img.narrowRgb, 1);
        ret = configMPP(mGscHandle, &mid_img, &dst_img);
        if (ret < 0) {
            ALOGE("failed to configure gscaler %u", mIndex);
            goto err_gsc_config;
        }

        ret = runMPP(mGscHandle, &mid_img, &dst_img);
        if (ret < 0) {
            ALOGE("failed to run gscaler %u", mIndex);
             goto err_gsc_config;
        }
        mMidBufFence[mCurrentBuf] = mid_img.releaseFenceFd;
    }

    mSrcConfig = src_img;
    mMidConfig = mid_img;

    if (need_gsc_op_twice) {
        mDstConfig = dst_img;
    } else {
        mDstConfig = mid_img;
    }

    layer.releaseFenceFd = src_img.releaseFenceFd;

    return 0;

err_gsc_config:
    destroyMPP(mGscHandle);
    mGscHandle = NULL;
err_alloc:
    if (src_img.acquireFenceFd >= 0)
        close(src_img.acquireFenceFd);
#ifdef USES_VIRTUAL_DISPLAY
    if (isNeedBufferAlloc) {
#endif
    for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++) {
       if (mDstBuffers[i]) {
           alloc_device->free(alloc_device, mDstBuffers[i]);
           mDstBuffers[i] = NULL;
       }
       if (mDstBufFence[i] >= 0) {
           close(mDstBufFence[i]);
           mDstBufFence[i] = -1;
       }
       if (mMidBuffers[i]) {
           alloc_device->free(alloc_device, mMidBuffers[i]);
           mMidBuffers[i] = NULL;
       }
       if (mMidBufFence[i] >= 0) {
           close(mMidBufFence[i]);
           mMidBufFence[i] = -1;
       }
    }
#ifdef USES_VIRTUAL_DISPLAY
    }
#endif
    memset(&mSrcConfig, 0, sizeof(mSrcConfig));
    memset(&mDstConfig, 0, sizeof(mDstConfig));
    memset(&mMidConfig, 0, sizeof(mMidConfig));
    return ret;
}
示例#2
0
void MediaPlayer::threadLoadMedia()
{
    m_duration = -1;
    m_errorsDetected = false;

    // Initialize gstreamer if not initialized yet
    if ( !gst_is_initialized() )
    {
        //qputenv( "GST_DEBUG", "*:4" );
#ifdef WIN32
        QString env = QString("GST_PLUGIN_PATH=%1\\gstreamer\\") .arg( QApplication::applicationDirPath() );
        env.replace( "/", "\\" );
        _putenv( qPrintable(env) );

        Logger::debug( "GstMediaPlayer: setting %s", qPrintable( env ) );
#endif
        gst_init(0, 0);
    }

    // Create the empty pipeline (this must be done first)
    m_gst_pipeline = gst_pipeline_new ("karaokepipeline");

    if ( !m_gst_pipeline )
    {
        reportError( "Pipeline could not be created." );
        return;
    }

    // Create the pipeline bus
    m_gst_bus = gst_element_get_bus( m_gst_pipeline );

    if ( !m_gst_bus )
    {
        reportError( "Pipeline bus could not be created." );
        return;
    }

    // Set the handler for the bus
    gst_bus_set_sync_handler( m_gst_bus, cb_busMessageDispatcher, this, 0 );

    // Create our media source, which could be either QIODevice/appsrc or a file
    // this also creates a decoder
    setupSource();

    // Those are mandatory
    if ( !m_gst_pipeline || !m_gst_source || !m_gst_decoder )
    {
        reportError( "Not all elements could be created." );
        return;
    }

    // Link and set up source and decoder if they are not the same object.
    if ( m_gst_source != m_gst_decoder )
    {
        if ( !gst_element_link( m_gst_source, m_gst_decoder ) )
        {
            reportError( "Cannot link source and decoder." );
            return;
        }
    }

    // If we do not have raw data, connect to the pad-added signal
    g_signal_connect( m_gst_decoder, "pad-added", G_CALLBACK (cb_pad_added), this );

    // Pre-create video elements if we need them
    if ( (m_loadOptions & MediaPlayer::LoadVideoStream) != 0 )
    {
        m_gst_video_colorconv = createElement( "videoconvert", "videoconvert" );
        m_gst_video_sink = createVideoSink();

        if ( !m_gst_video_colorconv || !m_gst_video_sink )
        {
            reportError( "Not all elements could be created." );
            return;
        }

        // Link the color converter and video sink
        if ( !gst_element_link( m_gst_video_colorconv, m_gst_video_sink ) )
        {
            reportError( "Cannor link video elements" );
            return;
        }
    }

    // Pre-create audio elements if we need them
    if ( (m_loadOptions & MediaPlayer::LoadAudioStream) != 0 )
    {
        // Load the pitch plugin if it is available
        m_pitchPlugin = pPluginManager->loadPitchChanger();

        // Create the audio elements, and add them to the bin
        m_gst_audioconverter = createElement ("audioconvert", "convert");
        m_gst_audio_volume = createElement("volume", "volume");
        m_gst_audiosink = createElement ("autoaudiosink", "sink");

        // Those are mandatory
        if ( !m_gst_audioconverter || !m_gst_audiosink || !m_gst_audio_volume )
        {
            reportError( "Not all elements could be created." );
            return;
        }

        // This one is optional, although it seems to be present everywhere
        m_gst_audio_tempo = createElement( "scaletempo", "tempo", false );

        // If we have the pitch changer
        if ( m_pitchPlugin && m_pitchPlugin->init() )
            m_gst_audio_pitchadjust = createElement( m_pitchPlugin->elementName(), "audiopitchchanger", false );
        else
            m_gst_audio_pitchadjust = 0;

        // Start linking
        bool linksucceed = true;
        GstElement * last = m_gst_audioconverter;

        if ( m_gst_audio_pitchadjust )
        {
            m_gst_audioconverter2 = createElement ("audioconvert", "convert2");

            linksucceed = gst_element_link_many( m_gst_audioconverter, m_gst_audio_pitchadjust, m_gst_audioconverter2, NULL );
            last = m_gst_audioconverter2;
        }

        // Now link in volume
        linksucceed = gst_element_link( last, m_gst_audio_volume );
        last = m_gst_audio_volume;

        // Now link in tempo if it is available
        if ( linksucceed && m_gst_audio_tempo )
        {
            linksucceed = gst_element_link( last, m_gst_audio_tempo );
            last = m_gst_audio_tempo;
        }

        // And finally the audio sink
        if ( linksucceed )
            linksucceed = gst_element_link( last, m_gst_audiosink );

        if ( !linksucceed )
        {
            reportError( "Audio elements could not be linked." );
            return;
        }
    }

    setPipelineState( GST_STATE_PAUSED );
}
int ExynosMPP::processOTF(hwc_layer_1_t &layer)
{
    ALOGV("configuring gscaler %u for memory-to-fimd-localout", mIndex);

    private_handle_t *src_handle = private_handle_t::dynamicCast(layer.handle);
    buffer_handle_t dst_buf;
    private_handle_t *dst_handle;
    int ret = 0;

    int srcAlign = sourceAlign(src_handle->format);
    int dstAlign;

    exynos_mpp_img src_img, dst_img;
    memset(&src_img, 0, sizeof(src_img));
    memset(&dst_img, 0, sizeof(dst_img));

    setupSource(src_img, layer);
    setupOtfDestination(src_img, dst_img, layer);

    dstAlign = destinationAlign(dst_img.format);

    ALOGV("source configuration:");
    dumpMPPImage(src_img);

    if (!mGscHandle || isSrcConfigChanged(src_img, mSrcConfig) ||
            isDstConfigChanged(dst_img, mDstConfig)) {

        if (!isPerFrameSrcChanged(src_img, mSrcConfig) ||
                !isPerFrameDstChanged(dst_img, mDstConfig)) {
            if (reconfigureOtf(&src_img, &dst_img) < 0)
                goto err_gsc_local;
        }
    }

    ALOGV("destination configuration:");
    dumpMPPImage(dst_img);

    ret = runMPP(mGscHandle, &src_img, &dst_img);
    if (ret < 0) {
        ALOGE("failed to run gscaler %u", mIndex);
        goto err_gsc_local;
    }

    memcpy(&mSrcConfig, &src_img, sizeof(mSrcConfig));
    memcpy(&mDstConfig, &dst_img, sizeof(mDstConfig));

    layer.releaseFenceFd = src_img.releaseFenceFd;
    return 0;

err_gsc_local:
    if (src_img.acquireFenceFd >= 0)
        close(src_img.acquireFenceFd);

    destroyMPP(mGscHandle);
    mGscHandle = NULL;

    memset(&mSrcConfig, 0, sizeof(mSrcConfig));
    memset(&mDstConfig, 0, sizeof(mDstConfig));

    return ret;
}