/** * \brief Task execution function * * In this function, all waits should use the wait function to ensure that * cancel is recognized. */ void ExposureWork::run() { debug(LOG_DEBUG, DEBUG_LOG, 0, "start ExposureWork"); // set the cooler if (cooler) { debug(LOG_DEBUG, DEBUG_LOG, 0, "turning on cooler"); cooler->setTemperature(_task.ccdtemperature()); cooler->setOn(true); } // set the filterwheel position std::string filtername("NONE"); if (filterwheel) { debug(LOG_DEBUG, DEBUG_LOG, 0, "selecting filter"); // make sure filter wheel is ready FilterwheelCondition condition(filterwheel, camera::FilterWheel::idle); if (!wait(10., condition)) { throw std::runtime_error("filterwheel did not settle"); } // select the new filter if (_task.filter().size() > 0) { filterwheel->select(_task.filter()); filtername = _task.filter(); } } // wait for the cooler, if present, but at most 30 seconds if (cooler) { debug(LOG_DEBUG, DEBUG_LOG, 0, "wait for cooler"); CoolerCondition coolercondition(cooler); if (!wait(30., coolercondition)) { debug(LOG_DEBUG, DEBUG_LOG, 0, "cannot stabilize temperature"); // XXX what do we do when the cooler cannot stabilize? } debug(LOG_DEBUG, DEBUG_LOG, 0, "cooler now stable"); } else { debug(LOG_DEBUG, DEBUG_LOG, 0, "no cooler"); } // wait for the filterwheel if present if (filterwheel) { debug(LOG_DEBUG, DEBUG_LOG, 0, "wait for filterwheel"); // wait once more for the filterwheel to become ready FilterwheelCondition condition(filterwheel, camera::FilterWheel::idle); if (!wait(30., condition)) { throw std::runtime_error("filter wheel does not idle"); } debug(LOG_DEBUG, DEBUG_LOG, 0, "filterwheel now idle"); } else { debug(LOG_DEBUG, DEBUG_LOG, 0, "no filter"); } // start exposure debug(LOG_DEBUG, DEBUG_LOG, 0, "start exposure: time=%f", _task.exposure().exposuretime()); ccd->startExposure(_task.exposure()); // wait for completion of exposure debug(LOG_DEBUG, DEBUG_LOG, 0, "waiting for %.3f seconds", _task.exposure().exposuretime()); CcdCondition ccdcondition(ccd, camera::CcdState::exposed); // if waiting is cancelled, then we have to cancel the exposure // also try { if (!wait(_task.exposure().exposuretime() + 30, ccdcondition)) { debug(LOG_DEBUG, DEBUG_LOG, 0, "waiting for image failed"); throw std::runtime_error("failed waiting for image"); } } catch (CancelException& x) { debug(LOG_DEBUG, DEBUG_LOG, 0, "cancel exception caught"); // cancel the image... ccd->cancelExposure(); debug(LOG_DEBUG, DEBUG_LOG, 0, "exposure cancelled, waiting"); // ... and wait until either the camera is in a safe state do { sleep(1); } while ((ccd->exposureStatus() == camera::CcdState::cancelling) || (ccd->exposureStatus() == camera::CcdState::exposing)); debug(LOG_DEBUG, DEBUG_LOG, 0, "wait comlete"); // now throw again to signal the work process that the process // was in fact cancelled throw; } // get the image from the ccd astro::image::ImagePtr image = ccd->getImage(); debug(LOG_DEBUG, DEBUG_LOG, 0, "image frame: %s", image->getFrame().toString().c_str()); // add instrument info if (_task.instrument().size() > 0) { image->setMetadata(FITSKeywords::meta("INSTRUME", _task.instrument())); } // add filter information to the image, if present if ((filterwheel) && (filtername.size() > 0)) { image->setMetadata(FITSKeywords::meta("FILTER", filtername)); } // add temperature metadata if (cooler) { cooler->addTemperatureMetadata(*image); } // position information from the mount if (mount) { mount->addPositionMetadata(*image); } // project inforamtion if (_task.project().size() > 0) { image->setMetadata(astro::io::FITSKeywords::meta( std::string("PROJECT"), _task.project())); } if (_task.repository().size() > 0) { // add the image to the repository std::string repository = _task.repository(); debug(LOG_DEBUG, DEBUG_LOG, 0, "saving image to imagerepo %s", repository.c_str()); project::ImageRepoPtr imagerepo = config::ImageRepoConfiguration::get()->repo(repository); if (imagerepo) { long id = imagerepo->save(image); _task.filename(stringprintf("%ld", id)); } else { debug(LOG_DEBUG, DEBUG_LOG, 0, "no image repo found"); } } else { // add to the ImageDirectory astro::image::ImageDatabaseDirectory imagedir; debug(LOG_DEBUG, DEBUG_LOG, 0, "saving image"); std::string filename = imagedir.save(image); // remember the filename _task.filename(filename); debug(LOG_DEBUG, DEBUG_LOG, 0, "saving image to file %s", filename.c_str()); } // update the frame information astro::camera::Exposure exposure = _task.exposure(); _task.exposure(exposure); // copy the returned image information _task.size(image->size()); _task.origin(image->origin()); // log info debug(LOG_DEBUG, DEBUG_LOG, 0, "image %s written", _task.filename().c_str()); _task.state(TaskQueueEntry::complete); }
void nemo_main() { int colnr[2]; real *coldat[2], *xdat, *ydat, xmin, xmax, ymin, ymax; real *udat, *vdat, umin, umax, vmin, vmax; real x, y1, y2, dx, xscale, yscale, xQmin, xQmax; real tbb,sum,sum0; stream instr, tabstr; int i, n, ns, nmax; real *sdat, *spdat; string spectrum, filter = filtername(getparam("filter")); bool Qnorm = getbparam("normalize"); bool Qmin = hasvalue("xmin"); bool Qmax = hasvalue("xmax"); bool Qtab = hasvalue("out"); nmax = nemo_file_lines(filter,MAXLINES); xdat = coldat[0] = (real *) allocate(nmax*sizeof(real)); ydat = coldat[1] = (real *) allocate(nmax*sizeof(real)); colnr[0] = 1; /* wavelenght in angstrom */ colnr[1] = 2; /* normalized filter response [0,1] */ instr = stropen(filter,"r"); n = get_atable(instr,2,colnr,coldat,nmax); strclose(instr); if (Qtab) tabstr = stropen(getparam("out"),"w"); for(i=0; i<n; i++) { dprintf(2,"%g %g\n",xdat[i],ydat[i]); if (i==0) { xmin = xmax = xdat[0]; ymin = ymax = ydat[0]; } else { if (xdat[i] <= xdat[i-1]) error("Filter %s must be sorted in wavelength",filter); xmax = MAX(xmax,xdat[i]); ymax = MAX(ymax,ydat[i]); xmin = MIN(xmin,xdat[i]); ymin = MIN(ymin,ydat[i]); } } dprintf(1,"Filter wavelength range: %g : %g\n",xmin,xmax); dprintf(1,"Filter response range: %g : %g\n",ymin,ymax); if (ydat[0] != 0) warning("lower edge filter response not 0: %g",ydat[0]); if (ydat[n-1] != 0) warning("upper edge filter response not 0: %g",ydat[n-1]); dx = getdparam("step"); if ((xmax-xmin)/100 < dx) { warning("Integration step %g in Angstrom too large, resetting to %g", dx, (xmax-xmin)/100); dx = (xmax-xmin)/100; } /* setup a spline interpolation table into the filter */ sdat = (real *) allocate(sizeof(real)*n*3); spline(sdat,xdat,ydat,n); if (Qmin) { /* override any min/max rules ? */ xQmin = getdparam("xmin"); if (xQmin > xmin) warning("xmin=%g greater than minimum in filter (%g)",xQmin,xmin); } if (Qmax) { xQmax = getdparam("xmax"); if (xQmax < xmax) warning("xmax=%g less than maximum in filter (%g)",xQmax,xmax); } if (hasvalue("tbb")) { /* using a Planck curve */ tbb = getdparam("tbb"); if (Qmin) xmin = xQmin; if (Qmax) xmax = xQmax; sum = sum0 = 0; for (x = xmin; x <= xmax; x += dx) { y1 = seval(x,xdat,ydat,sdat,n); /* filter */ y2 = planck(x,tbb); dprintf(3,"%g %g %g\n",x,y1,y2); if (Qtab) fprintf(tabstr,"%g %g\n",x,MAX(DATAMIN,y1*y2)); sum += y1*y2; sum0 += y1; } if (Qnorm) sum /= sum0; else sum *= dx; if (Qtab) dprintf(0,"%g %g %g\n",tbb,sum,-2.5*log10(sum)); else printf("%g %g %g\n",tbb,sum,-2.5*log10(sum)); } else if (hasvalue("spectrum")) { warning("spectrum= is a new feature"); spectrum = getparam("spectrum"); nmax = nemo_file_lines(spectrum,MAXLINES); udat = coldat[0] = (real *) allocate(nmax*sizeof(real)); vdat = coldat[1] = (real *) allocate(nmax*sizeof(real)); colnr[0] = getiparam("xcol"); colnr[1] = getiparam("ycol"); instr = stropen(spectrum,"r"); ns = get_atable(instr,2,colnr,coldat,nmax); strclose(instr); xscale = getdparam("xscale"); yscale = getdparam("yscale"); for(i=0; i<ns; i++) { dprintf(2,"%g %g\n",udat[i],vdat[i]); udat[i] *= xscale; vdat[i] *= yscale; if (i==0) { umin = umax = udat[0]; vmin = vmax = vdat[0]; } else { if (udat[i] <= udat[i-1]) error("Spectrum %s must be sorted in wavelength",spectrum); umax = MAX(umax,udat[i]); vmax = MAX(vmax,vdat[i]); umin = MIN(umin,udat[i]); vmin = MIN(vmin,vdat[i]); } } dprintf(1,"Spectrum wavelength range: %g : %g\n",umin,umax); dprintf(1,"Spectrum response range: %g : %g\n",vmin,vmax); if (umax < xmin || umin >xmax) error("Spectrum and filter do not overlap"); /* setup a spline interpolation table into the spectrum */ spdat = (real *) allocate(sizeof(real)*n*3); spline(spdat,udat,vdat,ns); sum = sum0 = 0; if (Qmin) xmin = xQmin; if (Qmax) xmax = xQmax; for (x = xmin; x <= xmax; x += dx) { y1 = seval(x,xdat,ydat,sdat,n); /* filter */ if (umin < x && x <umax) y2 = seval(x,udat,vdat,spdat,ns); /* spectrum */ else y2 = 0.0; dprintf(3,"%g %g %g\n",x,y1,y2); if (Qtab) fprintf(tabstr,"%g %g\n",x,MAX(DATAMIN,y1*y2)); sum += y1*y2; sum0 += y1; } if (Qnorm) sum /= sum0; else sum *= dx; if (Qtab) dprintf(0,"0 %g %g\n",sum,-2.5*log10(sum)); else printf("0 %g %g\n",sum,-2.5*log10(sum)); } else warning("Either spectrum= or tbb= must be used"); }
void Editor::importMovie( QString filePath, int fps ) { int i = 0; QSettings settings( PENCIL2D, PENCIL2D ); qDebug() << "-------IMPORT VIDEO------" << filePath; // --------- Import all the temporary frames ---------- QDir::temp().mkdir( "pencil" ); QString tempPath = QDir::temp().absolutePath() + "/pencil/"; if ( QFile::exists( QDir::current().currentPath() + "/plugins/ffmpeg.exe" ) == true ) { QProgressDialog progress( "Importing movie...", "Abort", 0, 100, NULL ); progress.setWindowModality( Qt::WindowModal ); progress.show(); progress.setValue( 10 ); QProcess ffmpeg; qDebug() << "./plugins/ffmpeg.exe -i \"" << filePath << "\" -r " << QString::number( fps ) << " -f image2 \"" << tempPath << "tmp_import%4d.png\""; ffmpeg.start( "./plugins/ffmpeg.exe -i \"" + filePath + "\" -r " + QString::number( fps ) + " -f image2 \"" + tempPath + "tmp_import%4d.png\"" ); progress.setValue( 20 ); if ( ffmpeg.waitForStarted() == true ) { if ( ffmpeg.waitForFinished() == true ) { qDebug() << "stdout: " + ffmpeg.readAllStandardOutput(); qDebug() << "stderr: " + ffmpeg.readAllStandardError(); } else { qDebug() << "ERROR: FFmpeg did not finish executing."; } } else { qDebug() << "ERROR: Could not execute FFmpeg."; } progress.setValue( 50 ); QDir dir1( tempPath ); int nFiles = dir1.entryList().count(); i = 1; QString frameNumberString = QString::number( i ); while ( frameNumberString.length() < 4 ) frameNumberString.prepend( "0" ); while ( QFile::exists( tempPath + "tmp_import" + frameNumberString + ".png" ) ) { progress.setValue( 50 + i * 50 / nFiles ); if ( i>1 ) scrubForward(); importImage( tempPath + "tmp_import" + frameNumberString + ".png" ); i++; frameNumberString = QString::number( i ); while ( frameNumberString.length() < 4 ) frameNumberString.prepend( "0" ); } progress.setValue( 100 ); // --------- Clean up temp directory --------- QDir dir( tempPath ); QStringList filtername( "*.*" ); QStringList entries = dir.entryList( filtername, QDir::Files, QDir::Type ); for ( int e = 0; e < entries.size(); e++ ) dir.remove( entries[ e ] ); } else { qDebug() << "Please place ffmpeg.exe in plugins directory"; } }
// added parameter exportFps -> frame rate of exported video // added parameter exportFormat -> to set ffmpeg parameters bool Object::exportMovie( ExportMovieParameters parameters ) { int startFrame = parameters.startFrame; int endFrame = parameters.endFrame; QTransform view = parameters.view; Layer* currentLayer = parameters.currentLayer; QSize exportSize = parameters.exportSize; QString filePath = parameters.filePath; int fps = parameters.fps; int exportFps = parameters.exportFps; QString exportFormat = parameters.exportFormat; if(!filePath.endsWith(".avi", Qt::CaseInsensitive)) { filePath = filePath + ".avi"; } // additional parameters for ffmpeg QString ffmpegParameter = ""; if(filePath.endsWith(".avi", Qt::CaseInsensitive)) {ffmpegParameter = " -vcodec msmpeg4 ";} if(filePath.endsWith(".mov", Qt::CaseInsensitive)) {ffmpegParameter = "";} if(filePath.endsWith(".mp4", Qt::CaseInsensitive)) {ffmpegParameter = "";} qDebug() << "-------VIDEO------"; // --------- Export all the temporary frames ---------- QDir::temp().mkdir("pencil"); QString tempPath = QDir::temp().absolutePath()+"/pencil/"; QProgressDialog progress("Exporting movie...", "Abort", 0, 100, NULL); progress.setWindowModality(Qt::WindowModal); progress.show(); QDir dir2(filePath); if (QFile::exists(filePath) == true) { dir2.remove(filePath); } const char* format = "png"; ExportFrames1Parameters par; par.frameStart = startFrame; par.frameEnd = endFrame; par.view = view; par.currentLayer = currentLayer; par.exportSize = exportSize; par.filePath = tempPath + "tmp"; par.format = format; par.quality = 100; par.background = true; par.antialiasing = true; par.progress = &progress; par.progressMax = 50; par.fps = fps; par.exportFps = exportFps; exportFrames1( par ); // --------- Quicktime assemble call ---------- QDir sampledir; qDebug() << "testmic:" << sampledir.filePath(filePath); QProcess ffmpeg; qDebug() << "Trying to export VIDEO"; quint32 audioDataSize = 44100*2*2*(endFrame-1)/fps; qint16* audioData =(qint16*) malloc(audioDataSize); for (uint i = 0; i < audioDataSize/2; i++ ) audioData[i] = 0; quint16 header1[22]; bool audioDataValid = false; for(int i = 0; i < this->getLayerCount() ; i++) { Layer* layer = this->getLayer(i); if(layer->type() == Layer::SOUND) { auto pSoundLayer = static_cast< LayerSound* >( layer ); pSoundLayer->foreachKeyFrame( [&] ( KeyFrame* key ) { int l = 0; // FIXME: export sound // convert audio file: 44100Hz sampling rate, stereo, signed 16 bit little endian // supported audio file types: wav, mp3, ogg... ( all file types supported by ffmpeg ) qDebug() << "ffmpeg -i \"" + ((LayerSound*)layer)->getSoundFilepathAt(l) + "\" -ar 44100 -acodec pcm_s16le -ac 2 -y \"" + tempPath + "tmpaudio0.wav\""; ffmpeg.start("ffmpeg -i \"" + ((LayerSound*)layer)->getSoundFilepathAt(l) + "\" -ar 44100 -acodec pcm_s16le -ac 2 -y \"" + tempPath + "tmpaudio0.wav\""); if (ffmpeg.waitForStarted() == true) { if (ffmpeg.waitForFinished() == true) { QByteArray sErr = ffmpeg.readAllStandardError(); if (sErr == "") { qDebug() << "ERROR: Could not execute FFmpeg."; } else { qDebug() << "stdout: " << ffmpeg.readAllStandardOutput(); qDebug() << "stderr: " << sErr; qDebug() << "AUDIO conversion done. ( file: " << ((LayerSound*)layer)->getSoundFilepathAt(l) << ")"; } } else { qDebug() << "ERROR: FFmpeg did not finish executing."; } } else { qDebug() << "ERROR: Could not execute FFmpeg."; } int frame = key->pos() - 1; float fframe = (float)frame/(float)fps; QFile file(tempPath+"tmpaudio0.wav"); qDebug() << "audio file " + tempPath+"tmpaudio0.wav"; file.open(QIODevice::ReadOnly); file.read((char*)header1,sizeof(header1)); quint32 audioSize = header1[21]; audioSize = audioSize * 65536 + header1[20]; qDebug() << "audio len " << audioSize; // before calling malloc should check: audioSize < max credible value qint16* data = (qint16*) malloc(audioSize); file.read((char*)data,audioSize); audioDataValid = true; int delta = fframe*44100*2; qDebug() << "audio delta " << delta; int indexMax = MIN(audioSize/2,audioDataSize/2-delta); // audio files 'mixing': 'higher' sound layers overwrite 'lower' sound layers for (int index = 0; index < indexMax; index++) { audioData[index+delta] = safeSum(audioData[index+delta],data[index]); } free(data); file.close(); } ); } } if ( audioDataValid ) { // save mixed audio file ( will be used as audio stream ) QFile file(tempPath+"tmpaudio.wav"); file.open(QIODevice::WriteOnly); header1[20] = audioDataSize % 65536; header1[21] = audioDataSize / 65536; file.write((char*)header1,sizeof(header1)); file.write((char*)audioData,audioDataSize); file.close(); } // video input: frame sequence ( -i tmp%03d.png ) // frame rate ( -r fps ) // audio input: ( -i tmpaudio.wav ) // movie output: ( filePath ) // frame rate ( -r 25 ) if ( audioDataValid ) { qDebug() << "ffmpeg -r " + QString::number(exportFps) + " -i " + tempPath + "tmp%4d.png -i " + tempPath + "tmpaudio.wav -r " + QString::number(exportFps) + " -y " + ffmpegParameter + "\"" + filePath + "\""; ffmpeg.start("ffmpeg -r " + QString::number(exportFps) + " -i " + tempPath + "tmp%4d.png -i " + tempPath + "tmpaudio.wav -r " + QString::number(exportFps) + " -y " + ffmpegParameter + "\"" + filePath + "\""); } else { qDebug() << "ffmpeg -r " + QString::number(exportFps) + " -i " + tempPath + "tmp%4d.png -r " + QString::number(exportFps) + " -y " + ffmpegParameter + "\"" + filePath + "\""; ffmpeg.start("ffmpeg -r " + QString::number(exportFps) + " -i " + tempPath + "tmp%4d.png -r " + QString::number(exportFps) + " -y " + ffmpegParameter + "\"" + filePath + "\""); } if (ffmpeg.waitForStarted() == true) { if (ffmpeg.waitForFinished() == true) { QByteArray sErr = ffmpeg.readAllStandardError(); if (sErr == "") { qDebug() << "ERROR: Could not execute FFmpeg."; } else { qDebug() << "stdout: " << ffmpeg.readAllStandardOutput(); qDebug() << "stderr: " << sErr; qDebug() << "dbg:" << QDir::current().currentPath() +"/plugins/"; qDebug() << ":" << tempPath + "tmp%03d.png"; qDebug() << ":\"" + filePath + "\""; qDebug() << "VIDEO export done."; } } else { qDebug() << "ERROR: FFmpeg did not finish executing."; } } else { qDebug() << "Please install FFMPEG: sudo apt-get install ffmpeg"; } progress.setValue(100); free(audioData); // --------- Clean up temp directory --------- QDir dir(tempPath); QStringList filtername("*.*"); QStringList entries = dir.entryList(filtername,QDir::Files,QDir::Type); for(int i=0; i<entries.size(); i++) dir.remove(entries[i]); qDebug() << "-----"; return true; }