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; }
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; }