]> git.sesse.net Git - nageru/blob - main.cpp
Hook up some more clip modifications.
[nageru] / main.cpp
1 #include <assert.h>
2 #include <stdio.h>
3 #include <stdint.h>
4
5 #include <chrono>
6 #include <memory>
7 #include <mutex>
8 #include <string>
9 #include <thread>
10 #include <vector>
11
12 extern "C" {
13 #include <libavformat/avformat.h>
14 }
15
16 #include <QApplication>
17
18 #include "mainwindow.h"
19 #include "ffmpeg_raii.h"
20 #include "post_to_main_thread.h"
21 #include "ui_mainwindow.h"
22
23 #define MAX_STREAMS 16
24
25 using namespace std;
26 using namespace std::chrono;
27
28 // TODO: Replace by some sort of GUI control, I guess.
29 int64_t current_pts = 0;
30
31 string filename_for_frame(unsigned stream_idx, int64_t pts)
32 {
33         char filename[256];
34         snprintf(filename, sizeof(filename), "frames/cam%d-pts%09ld.jpeg", stream_idx, pts);
35         return filename;
36 }
37
38 mutex frame_mu;
39 vector<int64_t> frames[MAX_STREAMS];
40
41 int thread_func();
42
43 int main(int argc, char **argv)
44 {
45         av_register_all();
46         avformat_network_init();
47
48         QApplication app(argc, argv);
49         MainWindow mainWindow;
50         mainWindow.show();
51
52         thread(thread_func).detach();
53
54         return app.exec();
55 }
56
57 int thread_func()
58 {
59         auto format_ctx = avformat_open_input_unique("multiangle.mp4", nullptr, nullptr);
60         if (format_ctx == nullptr) {
61                 fprintf(stderr, "%s: Error opening file\n", "example.mp4");
62                 return 1;
63         }
64
65         int64_t last_pts = -1;
66
67         for ( ;; ) {
68                 AVPacket pkt;
69                 unique_ptr<AVPacket, decltype(av_packet_unref)*> pkt_cleanup(
70                         &pkt, av_packet_unref);
71                 av_init_packet(&pkt);
72                 pkt.data = nullptr;
73                 pkt.size = 0;
74                 if (av_read_frame(format_ctx.get(), &pkt) != 0) {
75                         break;
76                 }
77                 fprintf(stderr, "Got a frame from camera %d, pts = %ld, size = %d\n",
78                         pkt.stream_index, pkt.pts, pkt.size);
79                 string filename = filename_for_frame(pkt.stream_index, pkt.pts);
80                 FILE *fp = fopen(filename.c_str(), "wb");
81                 if (fp == nullptr) {
82                         perror(filename.c_str());
83                         exit(1);
84                 }
85                 fwrite(pkt.data, pkt.size, 1, fp);
86                 fclose(fp);
87
88                 post_to_main_thread([pkt] {
89                         if (pkt.stream_index == 0) {
90                                 global_mainwindow->ui->input1_display->setFrame(pkt.stream_index, pkt.pts);
91                         } else if (pkt.stream_index == 1) {
92                                 global_mainwindow->ui->input2_display->setFrame(pkt.stream_index, pkt.pts);
93                         } else if (pkt.stream_index == 2) {
94                                 global_mainwindow->ui->input3_display->setFrame(pkt.stream_index, pkt.pts);
95                         }
96                 });
97
98                 assert(pkt.stream_index < MAX_STREAMS);
99                 frames[pkt.stream_index].push_back(pkt.pts);
100
101                 // Hack. Assumes a given timebase.
102                 if (last_pts != -1) {
103                         this_thread::sleep_for(microseconds((pkt.pts - last_pts) * 1000000 / 12800));
104                 }
105                 last_pts = pkt.pts;
106                 current_pts = pkt.pts;
107         }
108
109         return 0;
110 }