blob: ac24d68d065a97d923fc90385eb19a51e8d7272f [file] [log] [blame]
#include <unistd.h>
#include <cstdlib>
#include "absl/flags/flag.h"
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "aos/events/logging/log_reader.h"
#include "aos/events/simulated_event_loop.h"
#include "aos/init.h"
#include "aos/scoped/scoped_fd.h"
#include "frc971/vision/vision_generated.h"
ABSL_FLAG(std::string, channel, "/camera", "Channel name for the image.");
ABSL_FLAG(int32_t, width, 1280, "Width of the image");
ABSL_FLAG(int32_t, height, 720, "Height of the image");
ABSL_FLAG(std::string, ffmpeg_binary, "external/ffmpeg/ffmpeg",
"The path to the ffmpeg binary");
ABSL_FLAG(std::string, output_path, "video_ripper_output.mp4",
"The path to output the mp4 video");
ABSL_FLAG(bool, flip, true, "If true, rotate the video 180 deg.");
// Replays a log and dumps the contents of /camera frc971.vision.CameraImage
// directly to stdout.
int main(int argc, char *argv[]) {
aos::InitGoogle(&argc, &argv);
const std::vector<aos::logger::LogFile> logfiles =
aos::logger::SortParts(aos::logger::FindLogs(argc, argv));
CHECK(!logfiles.empty());
// Start ffmpeg
std::stringstream command;
command << absl::GetFlag(FLAGS_ffmpeg_binary);
command << " -framerate 30 -f rawvideo -pix_fmt yuyv422";
command << " -s " << absl::GetFlag(FLAGS_width) << "x"
<< absl::GetFlag(FLAGS_height);
command << " -i pipe:";
command << " -c:v libx264 -f mp4";
if (absl::GetFlag(FLAGS_flip)) {
command << " -vf rotate=PI";
}
command << " \"" << absl::GetFlag(FLAGS_output_path) << "\"";
FILE *stream = popen(command.str().c_str(), "w");
const std::string replay_node = logfiles.at(0).logger_node;
LOG(INFO) << "Replaying as \"" << replay_node << "\"";
aos::logger::LogReader reader(logfiles, nullptr);
aos::SimulatedEventLoopFactory factory(reader.configuration());
reader.RegisterWithoutStarting(&factory);
const aos::Node *node =
(replay_node.empty() ||
!aos::configuration::MultiNode(reader.configuration()))
? nullptr
: aos::configuration::GetNode(reader.configuration(), replay_node);
std::unique_ptr<aos::EventLoop> event_loop;
factory.GetNodeEventLoopFactory(node)->OnStartup([&stream, &event_loop,
&reader, node]() {
event_loop =
reader.event_loop_factory()->MakeEventLoop("video_ripper", node);
event_loop->MakeWatcher(
absl::GetFlag(FLAGS_channel),
[&stream](const frc971::vision::CameraImage &image) {
CHECK_EQ(absl::GetFlag(FLAGS_width), image.cols())
<< "Image width needs to match the images in the logfile";
CHECK_EQ(absl::GetFlag(FLAGS_height), image.rows())
<< "Image width needs to match the images in the logfile";
const size_t bytes_written =
write(fileno(stream), image.data()->data(), image.data()->size());
PCHECK(bytes_written == image.data()->size());
});
});
reader.event_loop_factory()->Run();
reader.Deregister();
pclose(stream);
}