Esempio n. 1
0
/**
Update tracks and settings from database.
*/
bool RecorderImpl::UpdateFromDatabase(unsigned int max_inputs, unsigned int max_tracks_per_input)
{
    bool ok = true;

    // Load recorder object from database
    prodauto::Recorder * rec = 0;
    try
    {
        rec = prodauto::Database::getInstance()->loadRecorder(mName);
    }
    catch (const prodauto::DBException & dbe)
    {
        ACE_DEBUG((LM_ERROR, ACE_TEXT("Database Exception: %C\n"), dbe.getMessage().c_str()));
        ok = false;
    }

    if (!rec)
    {
        // If there was a problem, re-initialise database and hope
        // for better luck next time.
        ACE_DEBUG((LM_WARNING, ACE_TEXT("Re-initialising database.\n")));
        DatabaseManager::Instance()->ReInitialise();
    }
    else
    {
        // Store the Recorder object
        mRecorder.reset(rec);

        // Update RecorderSettings
        RecorderSettings * settings = RecorderSettings::Instance();
        if (settings)
        {
            settings->Update(rec);
        }


        // Clear the set of SourceConfigs
        // and the various maps
        mSourceConfigs.clear();
        mTrackMap.clear();
        mTrackIndexMap.clear();
        mRecordingLocationMap.clear();

        // Set the source track names

        const unsigned int n_inputs = ACE_MIN((unsigned int)rec->recorderInputConfigs.size(), max_inputs);
        unsigned int track_i = 0;
        unsigned int n_video_tracks = 0;
        for (unsigned int i = 0; i < n_inputs; ++i)
        {
            prodauto::RecorderInputConfig * ric = rec->getInputConfig(i + 1);
            // We force number of tracks per input to be the hardware max because
            // this makes it easier to map to hardware parameters when filling out
            // tracks status with "signal present" etc.
            //const unsigned int n_tracks = ACE_MIN(ric->trackConfigs.size(), mMaxTracksPerInput);
            const unsigned int n_tracks = max_tracks_per_input;
            for (unsigned int j = 0; j < n_tracks; ++j)
            {
                prodauto::RecorderInputTrackConfig * ritc = 0;
                if (ric && j < ric->trackConfigs.size())
                {
                    ritc = ric->getTrackConfig(j + 1);
                }
                prodauto::SourceConfig * sc = 0;
                if (ritc)
                {
                    sc = ritc->sourceConfig;
                }
                prodauto::SourceTrackConfig * stc = 0;
                if (sc)
                {
                    stc = sc->getTrackConfig(ritc->sourceTrackID);
                }
            
                // Update our set of SourceConfig.  Actually using
                // a map with database ID as the key, simply because
                // having a pointer as a key is not good practice.
                if (sc)
                {
                    long id = sc->getDatabaseID();
                    mSourceConfigs[id] = sc;
                }

                // Update our map of RecordingLocation names
                if (sc)
                {
                    long id = sc->recordingLocation;
                    if (id)
                    {
                        try
                        {
                            mRecordingLocationMap[id] = prodauto::Database::getInstance()->loadLocationName(id);
                            ACE_DEBUG((LM_DEBUG, ACE_TEXT("Location %d \"%C\"\n"), id, mRecordingLocationMap[id].c_str()));
                        }
                        catch (const prodauto::DBException & dbe)
                        {
                            ACE_DEBUG((LM_ERROR, ACE_TEXT("Database Exception: %C\n"), dbe.getMessage().c_str()));
                        }
                    }
                }

                // Update map from source to hardware tracks
                if (stc)
                {
                    long id = stc->getDatabaseID();
                    HardwareTrack trk = {i, j};
                    mTrackMap[id] = trk;
                }

                // Note that here we assemble our list of tracks in harware order.
                // An alternative would be to present them in source order.  The
                // GUI already re-orders them in source order and presents them to
                // the user in that form.

                // Update map from source to mTracks index
                long stc_db_id = 0;
                if (stc)
                {
                    stc_db_id = stc->getDatabaseID();
                    // Check for duplicate input tracks
                    if (mTrackIndexMap.find(stc_db_id) != mTrackIndexMap.end())
                    {
                        ACE_DEBUG((LM_WARNING, ACE_TEXT("Warning: Duplicate input tracks connected! This is likely to cause problems.\n")));
                    }
                    mTrackIndexMap[stc_db_id] = track_i;
                }

                mTracks->length(track_i + 1);
                ProdAuto::Track & track = mTracks->operator[](track_i);

                // Set track type
                if (stc && stc->dataDef == PICTURE_DATA_DEFINITION)
                {
                    track.type = ProdAuto::VIDEO;
                    ++n_video_tracks;
                }
                else if (stc && stc->dataDef == SOUND_DATA_DEFINITION)
                {
                    track.type = ProdAuto::AUDIO;
                }
                // If no source track, assume hardware track 0 is video
                else if (j == 0)
                {
                    track.type = ProdAuto::VIDEO;
                    ++n_video_tracks;
                }
                else
                {
                    track.type = ProdAuto::AUDIO;
                }

#if 1
                // Name track by hardware input
                std::ostringstream s;
                if (track.type == ProdAuto::VIDEO)
                {
                    s << "V";
                }
                else
                {
                    track.type = ProdAuto::AUDIO;
                    s << "A" << j;
                }
                s << "  (input " << i << ")";
                track.name = CORBA::string_dup(s.str().c_str());
#else
                // Name track by source track name
                if (stc)
                {
                    track.name = CORBA::string_dup(stc->name.c_str());
                }
#endif

                // Set track id
                if (stc)
                {
                    track.id = stc->getDatabaseID(); // Helps to have this as used as key for maps
                }
                else
                {
                    // No source connected
                    track.id = 0;
                }

                if (sc && stc)
                {
                    track.has_source = 1;
                    track.src.package_name = CORBA::string_dup(sc->name.c_str());
                    prodauto::SourcePackage * sp = sc->getSourcePackage();
                    if (sp)
                    {
                        track.src.tape_name = CORBA::string_dup(sp->name.c_str());
                    }
                    else
                    {
                        track.src.tape_name = CORBA::string_dup("");
                    }
                    track.src.track_name = CORBA::string_dup(stc->name.c_str());
                }
                else
                {
                    // No connection to this input
                    track.has_source = 0;
                    track.src.package_name = CORBA::string_dup("zz No Connection");
                    track.src.tape_name = CORBA::string_dup("");
                    track.src.track_name = CORBA::string_dup("");
                }
                ACE_DEBUG((LM_DEBUG, ACE_TEXT("Input %d, track %d, databse id %3d, src.track_name \"%C\"\n"),
                    i, j, stc_db_id, (const char *) track.src.track_name));

                ++track_i;
            } // tracks
        } // inputs
        //mVideoTrackCount = n_video_tracks;

        // Re-initialise tracks status, if necessary.
        if (mTracksStatus->length() != mTracks->length())
        {
            mTracksStatus->length(mTracks->length());

            for (unsigned int i = 0; i < mTracksStatus->length(); ++i)
            {
                ProdAuto::TrackStatus & ts = mTracksStatus->operator[](i);
                ts.rec = 0;
                ts.rec_error = 0;
                ts.signal_present = 0;
                ts.timecode.undefined = true;
                //ts.timecode.edit_rate = mEditRate;
            }
        }
        ACE_DEBUG((LM_INFO, ACE_TEXT("Updated sources for recorder \"%C\"\n"), mRecorder->name.c_str()));
    }

    // Set source package names (using tape names if available)
    ok = ok && SetSourcePackages();

    return ok;
}
Esempio n. 2
0
/**
Final preparation for recording.
*/
void IngexRecorder::Setup(
                framecount_t start_timecode,
                const prodauto::ProjectName & project_name)
{
    ACE_DEBUG((LM_DEBUG, ACE_TEXT("IngexRecorder::Setup()\n")));

    // Get ProjectName associated with supplied name.
    //prodauto::ProjectName project_name;
    //GetProjectFromDb(project, project_name);

    // Store project name
    mProjectName = project_name;


    // Get current recorder settings
    RecorderSettings * settings = RecorderSettings::Instance();
    settings->Update(mpImpl->Recorder());

    /*
    switch (settings->timecode_mode)
    {
    case LTC_PARAMETER_VALUE:
        IngexShm::Instance()->TcMode(IngexShm::LTC);
        ACE_DEBUG((LM_DEBUG, ACE_TEXT("LTC mode\n")));
        break;
    case VITC_PARAMETER_VALUE:
        IngexShm::Instance()->TcMode(IngexShm::VITC);
        ACE_DEBUG((LM_DEBUG, ACE_TEXT("VITC mode\n")));
        break;
    default:
        ACE_DEBUG((LM_ERROR, ACE_TEXT("Unexpected timecode mode\n")));
        break;
    }
    */

    //unsigned int n_channels = IngexShm::Instance()->Channels();
    // Tracks per channel
    // e.g. 5 (1 video, 4 audio) or 9 (1 video, 8 audio)
    // A bit dodgy as different inputs on a recorder can have
    // different numbers of tracks.
    //mTracksPerChannel = track_enables.size() / channel_enables.size();

    int first_enabled_channel = -1;
    for (unsigned int i = 0; first_enabled_channel < 0 && i < mChannelEnable.size(); ++i)
    {
        if (mChannelEnable[i])
        {
            first_enabled_channel = i;
        }
    }

    // Create any needed paths.
    // NB. Paths need to be same as those used in recorder_fucntions.cpp
    for (std::vector<EncodeParams>::iterator it = settings->encodings.begin();
        it != settings->encodings.end(); ++it)
    {
        if (USE_PROJECT_SUBDIR)
        {
            std::string project_subdir = mProjectName.name;
            clean_filename(project_subdir);
            it->dir += PATH_SEPARATOR;
            it->dir += project_subdir;
            it->copy_dest += PATH_SEPARATOR;
            it->copy_dest += project_subdir;
        }

        FileUtils::CreatePath(it->dir);

        if (it->file_format == MXF_FILE_FORMAT_TYPE)
        {
            // Make Creating and Failures subdirs for MXF
            std::ostringstream creating_path;
            creating_path << it->dir << PATH_SEPARATOR << settings->mxf_subdir_creating;
            FileUtils::CreatePath(creating_path.str());
            std::ostringstream failures_path;
            failures_path << it->dir << PATH_SEPARATOR << settings->mxf_subdir_failures;
            FileUtils::CreatePath(failures_path.str());
            //std::ostringstream metadata_path;
            //metadata_path << it->dir << PATH_SEPARATOR << settings->mxf_subdir_metadata;
            //FileUtils::CreatePath(metadata_path.str());
        }
        else
        {
            // Make Creating subdir for other formats
            std::ostringstream creating_path;
            creating_path << it->dir << PATH_SEPARATOR << CREATING_SUBDIR;
            FileUtils::CreatePath(creating_path.str());
        }
    }

    // Set up encoding threads
    int encoding_i = 0;
    for (std::vector<EncodeParams>::const_iterator it = settings->encodings.begin();
        it != settings->encodings.end(); ++it, ++encoding_i)
    {
        if (it->source == Input::NORMAL)
        {
            for (unsigned int i = 0; i < mChannelEnable.size(); i++)
            {
                if (mChannelEnable[i])
                {
                    ThreadParam tp;
                    tp.p_rec = this;

                    tp.p_opt = new RecordOptions;
                    tp.p_opt->channel_num = i;
                    tp.p_opt->index = encoding_i;
                    
                    tp.p_opt->resolution = it->resolution;
                    tp.p_opt->file_format = it->file_format;
                    tp.p_opt->bitc = it->bitc;
                    tp.p_opt->dir = it->dir;

                    mThreadParams.push_back(tp);
                }
            }
        }
        else if (it->source == Input::QUAD)
        {
            ThreadParam tp;
            tp.p_rec = this;

            tp.p_opt = new RecordOptions;
            tp.p_opt->channel_num = first_enabled_channel;
            tp.p_opt->index = encoding_i;
            tp.p_opt->quad = true;
            tp.p_opt->resolution = it->resolution;
            tp.p_opt->file_format = it->file_format;
            tp.p_opt->bitc = it->bitc;
            tp.p_opt->dir = it->dir;

            mThreadParams.push_back(tp);
        }
    }
#if 0
// For test only, add a further encoding
    {
        ThreadParam tp;
        tp.p_rec = this;

        tp.p_opt = new RecordOptions;
        tp.p_opt->channel_num = 0;
        tp.p_opt->index = 2;
        
        tp.p_opt->resolution = 8;
        tp.p_opt->file_format = MXF_FILE_FORMAT_TYPE;
        tp.p_opt->bitc = true;
        tp.p_opt->dir = "/video/mxf_offline";

        mThreadParams.push_back(tp);
    }
#endif

    // Create and store filenames based on source, target timecode and date.
    ::Timecode tc(start_timecode, mFps, mDf);
    std::string date = DateTime::DateNoSeparators();
    const char * tcode = tc.TextNoSeparators();

    // We also include project name to help with copying to project-based
    // directories on a file-server.

    // Note that we make sure ident does not contain any unsuitable
    // characters such as '/'

    // Set filename stems in RecordOptions.
    for (std::vector<ThreadParam>::iterator
        it = mThreadParams.begin(); it != mThreadParams.end(); ++it)
    {
        const char * src_name = (it->p_opt->quad ? QUAD_NAME : SOURCE_NAME[it->p_opt->channel_num]);
        std::ostringstream ss;
        ss << date << "_" << tcode
            << "_" << mProjectName.name
            << "_" << mpImpl->Name()
            << "_" << src_name
            << "_" << it->p_opt->index;

        std::string ident = ss.str();
        clean_filename(ident);

        it->p_opt->file_ident = ident;
    }

    // Set up some of the user comments
    mUserComments.clear();
    mUserComments.push_back(
        prodauto::UserComment(AVID_UC_SHOOT_DATE_NAME, date.c_str(), STATIC_COMMENT_POSITION, 0));
}