@@ -410,24 +410,6 @@ void CircuitExplorerPlugin::init()
410410 _attachCircuitSimulationHandler (s);
411411 });
412412
413- PLUGIN_INFO << " Registering 'export-frames-to-disk' endpoint"
414- << std::endl;
415- _api->getActionInterface ()->registerNotification <ExportFramesToDisk>(
416- " export-frames-to-disk" ,
417- [&](const ExportFramesToDisk& s) { _exportFramesToDisk (s); });
418-
419- PLUGIN_INFO << " Registering 'get-export-frames-progress' endpoint"
420- << std::endl;
421- actionInterface->registerRequest <FrameExportProgress>(
422- " get-export-frames-progress" , [&](void ) -> FrameExportProgress {
423- return _getFrameExportProgress ();
424- });
425-
426- PLUGIN_INFO << " Registering 'make-movie' endpoint" << std::endl;
427- actionInterface->registerNotification <MakeMovieParameters>(
428- " make-movie" ,
429- [&](const MakeMovieParameters& params) { _makeMovie (params); });
430-
431413 PLUGIN_INFO << " Registering 'trace-anterograde' endpoint" << std::endl;
432414 _api->getActionInterface ()
433415 ->registerRequest <AnterogradeTracing, AnterogradeTracingResult>(
@@ -484,43 +466,6 @@ void CircuitExplorerPlugin::preRender()
484466 if (_dirty)
485467 _api->getScene ().markModified ();
486468 _dirty = false ;
487-
488- if (_exportFramesToDiskDirty && _accumulationFrameNumber == 0 )
489- {
490- const auto & ai = _exportFramesToDiskPayload.animationInformation ;
491- if (_frameNumber >= ai.size ())
492- _exportFramesToDiskDirty = false ;
493- else
494- {
495- const uint64_t i = 11 * _frameNumber;
496- // Camera position
497- CameraDefinition cd;
498- const auto & ci = _exportFramesToDiskPayload.cameraInformation ;
499- cd.origin = {ci[i], ci[i + 1 ], ci[i + 2 ]};
500- cd.direction = {ci[i + 3 ], ci[i + 4 ], ci[i + 5 ]};
501- cd.up = {ci[i + 6 ], ci[i + 7 ], ci[i + 8 ]};
502- cd.apertureRadius = ci[i + 9 ];
503- cd.focusDistance = ci[i + 10 ];
504- _setCamera (cd);
505-
506- // Animation parameters
507- _api->getParametersManager ().getAnimationParameters ().setFrame (
508- ai[_frameNumber]);
509- }
510- }
511- }
512-
513- void CircuitExplorerPlugin::postRender ()
514- {
515- if (_exportFramesToDiskDirty &&
516- _accumulationFrameNumber == _exportFramesToDiskPayload.spp )
517- {
518- _doExportFrameToDisk ();
519- ++_frameNumber;
520- _accumulationFrameNumber = 0 ;
521- }
522- else
523- ++_accumulationFrameNumber;
524469}
525470
526471void CircuitExplorerPlugin::_setMaterialExtraAttributes (
@@ -1047,203 +992,6 @@ void CircuitExplorerPlugin::_attachCircuitSimulationHandler(
1047992 }
1048993}
1049994
1050- void CircuitExplorerPlugin::_exportFramesToDisk (
1051- const ExportFramesToDisk& payload)
1052- {
1053- _exportFramesToDiskPayload = payload;
1054- _exportFramesToDiskDirty = true ;
1055- _frameNumber = payload.startFrame ;
1056- _accumulationFrameNumber = 0 ;
1057- auto & frameBuffer = _api->getEngine ().getFrameBuffer ();
1058- frameBuffer.clear ();
1059- PLUGIN_INFO << " -----------------------------------------------------------"
1060- " ---------------------"
1061- << std::endl;
1062- PLUGIN_INFO << " Movie settings :" << std::endl;
1063- PLUGIN_INFO << " - Number of frames : "
1064- << payload.animationInformation .size () - payload.startFrame
1065- << std::endl;
1066- PLUGIN_INFO << " - Samples per pixel: " << payload.spp << std::endl;
1067- PLUGIN_INFO << " - Frame size : " << frameBuffer.getSize ()
1068- << std::endl;
1069- PLUGIN_INFO << " - Export folder : " << payload.path << std::endl;
1070- PLUGIN_INFO << " - Start frame : " << payload.startFrame << std::endl;
1071- PLUGIN_INFO << " -----------------------------------------------------------"
1072- " ---------------------"
1073- << std::endl;
1074- }
1075-
1076- void CircuitExplorerPlugin::_doExportFrameToDisk ()
1077- {
1078- auto & frameBuffer = _api->getEngine ().getFrameBuffer ();
1079- auto image = frameBuffer.getImage ();
1080- auto fif = _exportFramesToDiskPayload.format == " jpg"
1081- ? FIF_JPEG
1082- : FreeImage_GetFIFFromFormat (
1083- _exportFramesToDiskPayload.format .c_str ());
1084- if (fif == FIF_JPEG)
1085- image.reset (FreeImage_ConvertTo24Bits (image.get ()));
1086- else if (fif == FIF_UNKNOWN)
1087- throw std::runtime_error (" Unknown format: " +
1088- _exportFramesToDiskPayload.format );
1089-
1090- int flags = _exportFramesToDiskPayload.quality ;
1091- if (fif == FIF_TIFF)
1092- flags = TIFF_NONE;
1093-
1094- brayns::freeimage::MemoryPtr memory (FreeImage_OpenMemory ());
1095-
1096- FreeImage_SaveToMemory (fif, image.get (), memory.get (), flags);
1097-
1098- BYTE* pixels = nullptr ;
1099- DWORD numPixels = 0 ;
1100- FreeImage_AcquireMemory (memory.get (), &pixels, &numPixels);
1101-
1102- char frame[7 ];
1103- sprintf (frame, " %05d" , _frameNumber);
1104- std::string filename = _exportFramesToDiskPayload.path + ' /' + frame + " ." +
1105- _exportFramesToDiskPayload.format ;
1106- std::ofstream file;
1107- file.open (filename, std::ios_base::binary);
1108- if (!file.is_open ())
1109- PLUGIN_THROW (" Failed to create " + filename);
1110-
1111- file.write ((char *)pixels, numPixels);
1112- file.close ();
1113-
1114- frameBuffer.clear ();
1115-
1116- PLUGIN_INFO << " Frame saved to " << filename << std::endl;
1117- }
1118-
1119- FrameExportProgress CircuitExplorerPlugin::_getFrameExportProgress ()
1120- {
1121- FrameExportProgress result;
1122- const size_t totalNumberOfFrames =
1123- (_exportFramesToDiskPayload.animationInformation .size () -
1124- _exportFramesToDiskPayload.startFrame ) *
1125- _exportFramesToDiskPayload.spp ;
1126- const float currentProgress =
1127- _frameNumber * _exportFramesToDiskPayload.spp +
1128- _accumulationFrameNumber;
1129-
1130- result.progress = currentProgress / float (totalNumberOfFrames);
1131- return result;
1132- }
1133-
1134- void CircuitExplorerPlugin::_makeMovie (const MakeMovieParameters& params)
1135- {
1136- // Find ffmpeg executable path
1137- std::array<char , 256 > buffer;
1138- std::string ffmpegPath;
1139- std::unique_ptr<FILE, decltype (&pclose)> pipe (popen (" which ffmpeg" , " r" ),
1140- pclose);
1141- if (!pipe)
1142- {
1143- PLUGIN_ERROR << " Could not launch movie creation: ffmpeg not found"
1144- << std::endl;
1145- return ;
1146- }
1147- while (fgets (buffer.data (), buffer.size (), pipe.get ()) != nullptr )
1148- {
1149- ffmpegPath += buffer.data ();
1150- }
1151-
1152- // Remove new lines
1153- size_t pos = std::string::npos;
1154- do
1155- {
1156- pos = ffmpegPath.find (" \n " );
1157- if (pos != std::string::npos)
1158- {
1159- ffmpegPath.replace (pos, pos + 2 , " " );
1160- }
1161- } while (pos != std::string::npos);
1162-
1163- // Get sanitetized string inputs
1164- std::string sanitizedFramesFolder = params.framesFolderPath ;
1165- const std::string slash =
1166- sanitizedFramesFolder[sanitizedFramesFolder.length () - 1 ] == ' /' ? " "
1167- : " /" ;
1168-
1169- std::string sanitizedFramesExt = params.framesFileExtension ;
1170- std::string sanitizedOutputPath = params.outputMoviePath ;
1171-
1172- sanitizedFramesFolder = _sanitizeString (sanitizedFramesFolder);
1173- sanitizedFramesExt = _sanitizeString (sanitizedFramesExt);
1174- sanitizedOutputPath = _sanitizeString (sanitizedOutputPath);
1175-
1176- const std::string inputParam =
1177- sanitizedFramesFolder + slash + " %05d." + sanitizedFramesExt;
1178- const std::string filterParam =
1179- " scale=" + std::to_string (static_cast <int >(params.dimensions [0 ])) +
1180- " :" + std::to_string (static_cast <int >(params.dimensions [1 ])) +
1181- " ,format=yuv420p" ;
1182- const pid_t pid = fork ();
1183-
1184- if (pid == 0 )
1185- {
1186- execl (ffmpegPath.c_str (), " ffmpeg" , " -y" , " -hide_banner" , " -loglevel" ,
1187- " 0" , " -r" , std::to_string (params.fpsRate ).c_str (), " -i" ,
1188- inputParam.c_str (), " -vf" , filterParam.c_str (), " -crf" , " 0" ,
1189- " -codec:v" , " libx264" , sanitizedOutputPath.c_str (),
1190- static_cast <char *>(nullptr ));
1191- }
1192- else
1193- {
1194- int status = 0 ;
1195- if (waitpid (pid, &status, 0 ) > 0 )
1196- {
1197- // If we could not make the movie, inform and stop execution
1198- if (WIFEXITED (status) && WEXITSTATUS (status))
1199- {
1200- if (WEXITSTATUS (status) == 127 )
1201- {
1202- PLUGIN_ERROR << " Could not create media video file. FFMPEG "
1203- " returned with error "
1204- << status << std::endl;
1205- return ;
1206- }
1207- }
1208- }
1209- else
1210- {
1211- PLUGIN_ERROR << " Could not create media video file. "
1212- " Could not launch FFMPEG."
1213- << std::endl;
1214- return ;
1215- }
1216- }
1217-
1218- if (params.eraseFrames )
1219- {
1220- DIR* dir;
1221- struct dirent * ent;
1222- const std::regex fileNameRegex (" [0-9]{5}." +
1223- params.framesFileExtension );
1224- if ((dir = opendir (params.framesFolderPath .c_str ())) != nullptr )
1225- {
1226- while ((ent = readdir (dir)) != nullptr )
1227- {
1228- std::string fileName (ent->d_name );
1229- if (std::regex_match (fileName, fileNameRegex))
1230- {
1231- const std::string fullPath =
1232- sanitizedFramesFolder + slash + fileName;
1233- PLUGIN_INFO << " Cleaning frame " << fullPath << std::endl;
1234- remove (fullPath.c_str ());
1235- }
1236- }
1237- closedir (dir);
1238- }
1239- else
1240- {
1241- PLUGIN_ERROR << " make-movie: Could not clean up frames"
1242- << std::endl;
1243- }
1244- }
1245- }
1246-
1247995AnterogradeTracingResult CircuitExplorerPlugin::_traceAnterogrades (
1248996 const AnterogradeTracing& payload)
1249997{
0 commit comments