Beispiel #1
0
void
DiskCacheNode::fetchRenderCloneKnobs()
{
    EffectInstance::fetchRenderCloneKnobs();
    _imp->frameRange = toKnobChoice(getKnobByName(kDiskCacheNodeFrameRange));
    _imp->firstFrame = toKnobInt(getKnobByName(kDiskCacheNodeFirstFrame));
    _imp->lastFrame = toKnobInt(getKnobByName(kDiskCacheNodeLastFrame));
}
Beispiel #2
0
void
OutputEffectInstance::createWriterPath()
{
    ///Make sure that the file path exists
    KnobPtr fileParam = getKnobByName(kOfxImageEffectFileParamName);

    if (fileParam) {
        Knob<std::string>* isString = dynamic_cast<Knob<std::string>*>( fileParam.get() );
        if (isString) {
            std::string pattern = isString->getValue();
            std::string path = SequenceParsing::removePath(pattern);
            std::map<std::string, std::string> env;
            getApp()->getProject()->getEnvironmentVariables(env);
            Project::expandVariable(env, path);
            if ( !path.empty() ) {
                QDir().mkpath( QString::fromUtf8( path.c_str() ) );
            }
        }
    }
}
void
RotoShapeRenderNode::fetchRenderCloneKnobs()
{
    RotoDrawableItemPtr mainInstanceItem = getOriginalAttachedItem();
    assert(mainInstanceItem);
    FrameViewRenderKey key = {getCurrentRenderTime(), getCurrentRenderView(), getCurrentRender()};
    KnobHolderPtr itemClone = mainInstanceItem->createRenderClone(key);
    assert(itemClone);
    (void)itemClone;

    assert(isRenderClone());
    EffectInstance::fetchRenderCloneKnobs();
    _imp->renderType = toKnobChoice(getKnobByName(kRotoShapeRenderNodeParamType));
    _imp->outputRoDTypeKnob = toKnobChoice(getKnobByName(kRotoOutputRodType));
    _imp->outputFormatKnob = toKnobChoice(getKnobByName(kRotoFormatParam));
    _imp->outputFormatSizeKnob = toKnobInt(getKnobByName(kRotoFormatSize));
    assert(_imp->outputFormatSizeKnob.lock());
    _imp->outputFormatParKnob = toKnobDouble(getKnobByName(kRotoFormatPar));
    _imp->clipToFormatKnob = toKnobBool(getKnobByName(kRotoClipToFormatParam));
}
Beispiel #4
0
void
OutputEffectInstance::reportStats(int time,
                                  ViewIdx view,
                                  double wallTime,
                                  const std::map<NodePtr, NodeRenderStats > & stats)
{
    std::string filename;
    KnobPtr fileKnob = getKnobByName(kOfxImageEffectFileParamName);

    if (fileKnob) {
        KnobOutputFile* strKnob = dynamic_cast<KnobOutputFile*>( fileKnob.get() );
        if  (strKnob) {
            QString qfileName = QString::fromUtf8( SequenceParsing::generateFileNameFromPattern(strKnob->getValue( 0, ViewIdx(view) ), getApp()->getProject()->getProjectViewNames(), time, view).c_str() );
            QtCompat::removeFileExtension(qfileName);
            qfileName.append( QString::fromUtf8("-stats.txt") );
            filename = qfileName.toStdString();
        }
    }

    //If there's no filename knob, do not write anything
    if ( filename.empty() ) {
        std::cout << tr("Cannot write render statistics file: "
                        "%1 does not seem to have a parameter named \"filename\" "
                        "to determine the location where to write the stats file.")
            .arg( QString::fromUtf8( getScriptName_mt_safe().c_str() ) ).toStdString();

        return;
    }


    FStreamsSupport::ofstream ofile;
    FStreamsSupport::open(&ofile, filename);
    if (!ofile) {
        std::cout << tr("Failure to write render statistics file.").toStdString() << std::endl;

        return;
    }

    ofile << "Time spent to render frame (wall clock time): " << Timer::printAsTime(wallTime, false).toStdString() << std::endl;
    for (std::map<NodePtr, NodeRenderStats >::const_iterator it = stats.begin(); it != stats.end(); ++it) {
        ofile << "------------------------------- " << it->first->getScriptName_mt_safe() << "------------------------------- " << std::endl;
        ofile << "Time spent rendering: " << Timer::printAsTime(it->second.getTotalTimeSpentRendering(), false).toStdString() << std::endl;
        const RectD & rod = it->second.getRoD();
        ofile << "Region of definition: x1 = " << rod.x1  << " y1 = " << rod.y1 << " x2 = " << rod.x2 << " y2 = " << rod.y2 << std::endl;
        ofile << "Is Identity to Effect? ";
        NodePtr identity = it->second.getInputImageIdentity();
        if (identity) {
            ofile << "Yes, to " << identity->getScriptName_mt_safe() << std::endl;
        } else {
            ofile << "No" << std::endl;
        }
        ofile << "Has render-scale support? ";
        if ( it->second.isRenderScaleSupportEnabled() ) {
            ofile << "Yes";
        } else {
            ofile << "No";
        }
        ofile << std::endl;
        ofile << "Has tiles support? ";
        if ( it->second.isTilesSupportEnabled() ) {
            ofile << "Yes";
        } else {
            ofile << "No";
        }
        ofile << std::endl;
        ofile << "Channels processed: ";

        std::bitset<4> processChannels = it->second.getChannelsRendered();
        if (processChannels[0]) {
            ofile << "red ";
        }
        if (processChannels[1]) {
            ofile << "green ";
        }
        if (processChannels[2]) {
            ofile << "blue ";
        }
        if (processChannels[3]) {
            ofile << "alpha";
        }
        ofile << std::endl;

        ofile << "Output alpha premultiplication: ";
        switch ( it->second.getOutputPremult() ) {
        case eImagePremultiplicationOpaque:
            ofile << "opaque";
            break;
        case eImagePremultiplicationPremultiplied:
            ofile << "premultiplied";
            break;
        case eImagePremultiplicationUnPremultiplied:
            ofile << "unpremultiplied";
            break;
        }
        ofile << std::endl;

        ofile << "Mipmap level(s) rendered: ";
        for (std::set<unsigned int>::const_iterator it2 = it->second.getMipMapLevelsRendered().begin(); it2 != it->second.getMipMapLevelsRendered().end(); ++it2) {
            ofile << *it2 << ' ';
        }
        ofile << std::endl;
        int nbCacheMiss, nbCacheHit, nbCacheHitButDownscaled;
        it->second.getCacheAccessInfos(&nbCacheMiss, &nbCacheHit, &nbCacheHitButDownscaled);
        ofile << "Nb cache hit: " << nbCacheMiss << std::endl;
        ofile << "Nb cache miss: " << nbCacheMiss << std::endl;
        ofile << "Nb cache hit requiring mipmap downscaling: " << nbCacheHitButDownscaled << std::endl;

        const std::set<std::string> & planes = it->second.getPlanesRendered();
        ofile << "Plane(s) rendered: ";
        for (std::set<std::string>::const_iterator it2 = planes.begin(); it2 != planes.end(); ++it2) {
            ofile << *it2 << ' ';
        }
        ofile << std::endl;

        std::list<std::pair<RectI, NodePtr > > identityRectangles = it->second.getIdentityRectangles();
        const std::list<RectI> & renderedRectangles = it->second.getRenderedRectangles();

        ofile << "Identity rectangles: " << identityRectangles.size() << std::endl;
        for (std::list<std::pair<RectI, NodePtr > > ::iterator it2 = identityRectangles.begin(); it2 != identityRectangles.end(); ++it2) {
            ofile << "Origin: " << it2->second->getScriptName_mt_safe() << ", rect: x1 = " << it2->first.x1
                  << " y1 = " << it2->first.y1 << " x2 = " << it2->first.x2 << " y2 = " << it2->first.y2 << std::endl;
        }

        ofile << "Rectangles rendered: " << renderedRectangles.size() << std::endl;
        for (std::list<RectI>::const_iterator it2 = renderedRectangles.begin(); it2 != renderedRectangles.end(); ++it2) {
            ofile << "x1 = " << it2->x1 << " y1 = " << it2->y1 << " x2 = " << it2->x2 << " y2 = " << it2->y2 << std::endl;
        }
    }
} // OutputEffectInstance::reportStats
Beispiel #5
0
void
OutputEffectInstance::renderFullSequence(bool isBlocking,
                                         bool enableRenderStats,
                                         BlockingBackgroundRender* renderController,
                                         int first,
                                         int last,
                                         int frameStep)
{
    int viewsCount = getApp()->getProject()->getProjectViewsCount();
    const ViewIdx mainView(0);
    std::vector<ViewIdx> viewsToRender(viewsCount);

    for (int i = 0; i < viewsCount; ++i) {
        viewsToRender[i] = ViewIdx(i);
    }

    ///The effect is sequential (e.g: WriteFFMPEG), and thus cannot render multiple views, we have to choose one
    ///We pick the user defined main view in the project settings
    SequentialPreferenceEnum sequentiallity = getSequentialPreference();
    bool canOnlyHandleOneView = sequentiallity == eSequentialPreferenceOnlySequential || sequentiallity == eSequentialPreferencePreferSequential;

    if (canOnlyHandleOneView) {
        viewsToRender.clear();
        viewsToRender.push_back(mainView);
    }

    if ( isViewAware() ) {
        //If the Writer is view aware, check if it wants to render all views at once or not
        KnobPtr outputFileNameKnob = getKnobByName(kOfxImageEffectFileParamName);
        if (outputFileNameKnob) {
            KnobOutputFile* outputFileName = dynamic_cast<KnobOutputFile*>( outputFileNameKnob.get() );
            assert(outputFileName);
            if (outputFileName) {
                std::string pattern = outputFileName->getValue();
                std::size_t foundViewPattern = pattern.find_first_of("%v");
                if (foundViewPattern == std::string::npos) {
                    foundViewPattern = pattern.find_first_of("%V");
                }
                if (foundViewPattern == std::string::npos) {
                    ///No view pattern
                    ///all views will be overwritten to the same file
                    ///If this is WriteOIIO, check the parameter "viewsSelector" to determine if the user wants to encode all
                    ///views to a single file or not
                    KnobPtr viewsKnob = getKnobByName(kWriteOIIOParamViewsSelector);
                    bool hasViewChoice = false;
                    if ( viewsKnob && !viewsKnob->getIsSecret() ) {
                        KnobChoice* viewsChoice = dynamic_cast<KnobChoice*>( viewsKnob.get() );
                        if (viewsChoice) {
                            hasViewChoice = true;
                            int viewChoice_i = viewsChoice->getValue();
                            if (viewChoice_i == 0) { // the "All" choice
                                viewsToRender.clear();
                                // note: if the plugin renders all views to a single file, then rendering view 0 will do the job.
                                viewsToRender.push_back( ViewIdx(0) );
                            } else {
                                //The user has specified a view
                                viewsToRender.clear();
                                assert(viewChoice_i >= 1);
                                viewsToRender.push_back( ViewIdx(viewChoice_i - 1) );
                            }
                        }
                    }
                    if (!hasViewChoice) {
                        if (viewsToRender.size() > 1) {
                            std::string mainViewName;
                            const std::vector<std::string>& viewNames = getApp()->getProject()->getProjectViewNames();
                            if ( mainView < (int)viewNames.size() ) {
                                mainViewName = viewNames[mainView];
                            }
                            QString message = tr("%1 does not support multi-view, only the view %2 will be rendered.")
                                              .arg( QString::fromUtf8( getNode()->getLabel_mt_safe().c_str() ) )
                                              .arg( QString::fromUtf8( mainViewName.c_str() ) );
                            if (!renderController) {
                                message.append( QChar::fromLatin1('\n') );
                                message.append( QString::fromUtf8("You can use the %v or %V indicator in the filename to render to separate files.\n"
                                                                  "Would you like to continue?") );
                                StandardButtonEnum rep = Dialogs::questionDialog(tr("Multi-view support").toStdString(), message.toStdString(), false, StandardButtons(eStandardButtonOk | eStandardButtonCancel), eStandardButtonOk);
                                if (rep != eStandardButtonOk) {
                                    return;
                                }
                            } else {
                                Dialogs::warningDialog( tr("Multi-view support").toStdString(), message.toStdString() );
                            }
                        }
                        //Render the main-view only...
                        viewsToRender.clear();
                        viewsToRender.push_back(mainView);
                    }
                } else {
                    ///The user wants to write each view into a separate file
                    ///This will disregard the content of kWriteOIIOParamViewsSelector and the Writer
                    ///should write one view per-file.
                }
            }
        }
    } else { // !isViewAware
        if (viewsToRender.size() > 1) {
            std::string mainViewName;
            const std::vector<std::string>& viewNames = getApp()->getProject()->getProjectViewNames();
            if ( mainView < (int)viewNames.size() ) {
                mainViewName = viewNames[mainView];
            }
            QString message = tr("%1 does not support multi-view, only the view %2 will be rendered.")
                              .arg( QString::fromUtf8( getNode()->getLabel_mt_safe().c_str() ) )
                              .arg( QString::fromUtf8( mainViewName.c_str() ) );
            if (!renderController) {
                message.append( QChar::fromLatin1('\n') );
                message.append( QString::fromUtf8("You can use the %v or %V indicator in the filename to render to separate files.\n"
                                                  "Would you like to continue?") );
                StandardButtonEnum rep = Dialogs::questionDialog(tr("Multi-view support").toStdString(), message.toStdString(), false, StandardButtons(eStandardButtonOk | eStandardButtonCancel), eStandardButtonOk);
                if (rep != eStandardButtonOk) {
                    return;
                }
            } else {
                Dialogs::warningDialog( tr("Multi-view support").toStdString(), message.toStdString() );
            }
        }
    }


    RenderSequenceArgs args;
    {
        QMutexLocker k(&_outputEffectDataLock);
        args.firstFrame = first;
        args.lastFrame = last;
        args.frameStep = frameStep;
        args.renderController = renderController;
        args.useStats = enableRenderStats;
        args.blocking = isBlocking;
        args.viewsToRender = viewsToRender;
        _renderSequenceRequests.push_back(args);
        if (_renderSequenceRequests.size() > 1) {
            //The node is already rendering a sequence, queue it and dequeue it in notifyRenderFinished()
            return;
        }
    }
    launchRenderSequence(args);
} // OutputEffectInstance::renderFullSequence