blob: 3c931391e2888c0ebc1064c113c371e739a9868f [file] [log] [blame]
Ravago Jones3b4fd912023-03-18 13:35:17 -07001#include <unistd.h>
2
3#include <cstdlib>
4
5#include "gflags/gflags.h"
6#include "glog/logging.h"
7
8#include "aos/events/logging/log_reader.h"
9#include "aos/events/simulated_event_loop.h"
10#include "aos/init.h"
11#include "aos/scoped/scoped_fd.h"
12#include "frc971/vision/vision_generated.h"
13
14DEFINE_string(channel, "/camera", "Channel name for the image.");
15DEFINE_int32(width, 1280, "Width of the image");
16DEFINE_int32(height, 720, "Height of the image");
17DEFINE_string(ffmpeg_binary, "external/ffmpeg/ffmpeg",
18 "The path to the ffmpeg binary");
19DEFINE_string(output_path, "video_ripper_output.mp4",
20 "The path to output the mp4 video");
21DEFINE_bool(flip, true, "If true, rotate the video 180 deg.");
22
23// Replays a log and dumps the contents of /camera frc971.vision.CameraImage
24// directly to stdout.
25int main(int argc, char *argv[]) {
26 aos::InitGoogle(&argc, &argv);
27 const std::vector<aos::logger::LogFile> logfiles =
28 aos::logger::SortParts(aos::logger::FindLogs(argc, argv));
29 CHECK(!logfiles.empty());
30
31 // Start ffmpeg
32 std::stringstream command;
33 command << FLAGS_ffmpeg_binary;
34 command << " -framerate 30 -f rawvideo -pix_fmt yuyv422";
35 command << " -s " << FLAGS_width << "x" << FLAGS_height;
36 command << " -i pipe:";
37 command << " -c:v libx264 -f mp4";
38 if (FLAGS_flip) {
39 command << " -vf rotate=PI";
40 }
41 command << " \"" << FLAGS_output_path << "\"";
42
43 FILE *stream = popen(command.str().c_str(), "w");
44
45 const std::string replay_node = logfiles.at(0).logger_node;
46 LOG(INFO) << "Replaying as \"" << replay_node << "\"";
47
48 aos::logger::LogReader reader(logfiles, nullptr);
49 aos::SimulatedEventLoopFactory factory(reader.configuration());
50 reader.RegisterWithoutStarting(&factory);
51
52 const aos::Node *node =
53 (replay_node.empty() ||
54 !aos::configuration::MultiNode(reader.configuration()))
55 ? nullptr
56 : aos::configuration::GetNode(reader.configuration(), replay_node);
57
58 std::unique_ptr<aos::EventLoop> event_loop;
59 factory.GetNodeEventLoopFactory(node)->OnStartup([&stream, &event_loop,
60 &reader, node]() {
61 event_loop =
62 reader.event_loop_factory()->MakeEventLoop("video_ripper", node);
63 event_loop->MakeWatcher(
64 FLAGS_channel, [&stream](const frc971::vision::CameraImage &image) {
65 CHECK_EQ(FLAGS_width, image.cols())
66 << "Image width needs to match the images in the logfile";
67 CHECK_EQ(FLAGS_height, image.rows())
68 << "Image width needs to match the images in the logfile";
69
70 const size_t bytes_written =
71 write(fileno(stream), image.data()->data(), image.data()->size());
72 PCHECK(bytes_written == image.data()->size());
73 });
74 });
75
76 reader.event_loop_factory()->Run();
77 reader.Deregister();
78
79 pclose(stream);
80}