X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=futatabi%2Fmain.cpp;h=3146aa52d5eb2f55bf6d0fd0ca9adede42fab95f;hb=b168e72fcdcd17be5c578f2232e40c2347c3ff98;hp=46fb200eb149f47eba370d7a23697d992eda463d;hpb=539609eb56b496e6eff8a5e0a92fa0325936a5d7;p=nageru diff --git a/futatabi/main.cpp b/futatabi/main.cpp index 46fb200..3146aa5 100644 --- a/futatabi/main.cpp +++ b/futatabi/main.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include extern "C" { @@ -22,7 +23,7 @@ extern "C" { #include "clip_list.h" #include "shared/context.h" #include "defs.h" -#include "disk_space_estimator.h" +#include "shared/disk_space_estimator.h" #include "shared/ffmpeg_raii.h" #include "flags.h" #include "frame_on_disk.h" @@ -169,7 +170,7 @@ FrameOnDisk write_frame(int stream_idx, int64_t pts, const uint8_t *data, size_t const char *basename = filename.c_str(); while (strchr(basename, '/') != nullptr) { - basename = strchr(basename, '/'); + basename = strchr(basename, '/') + 1; } db->store_frame_file(basename, size, frames_this_file); } @@ -199,13 +200,11 @@ int main(int argc, char **argv) string frame_dir = global_flags.working_directory + "/frames"; - struct stat st; - if (stat(frame_dir.c_str(), &st) == -1) { + if (mkdir(frame_dir.c_str(), 0777) == 0) { fprintf(stderr, "%s does not exist, creating it.\n", frame_dir.c_str()); - if (mkdir(frame_dir.c_str(), 0777) == -1) { - perror(global_flags.working_directory.c_str()); - exit(1); - } + } else if (errno != EEXIST) { + perror(global_flags.working_directory.c_str()); + exit(1); } avformat_network_init(); @@ -239,7 +238,10 @@ int main(int argc, char **argv) { QSurface *surface = create_surface(); QOpenGLContext *context = create_context(surface); - make_current(context, surface); + if (!make_current(context, surface)) { + printf("oops\n"); + exit(1); + } CHECK(movit::init_movit(MOVIT_SHADER_DIR, movit::MOVIT_DEBUG_OFF)); delete_context(context); // TODO: Delete the surface, too. @@ -278,7 +280,7 @@ void load_frame_file(const char *filename, const string &basename, unsigned file if (!all_frames.empty()) { // We already had this cached in the database, so no need to look in the file. for (const DB::FrameOnDiskAndStreamIdx &frame : all_frames) { - if (frame.stream_idx >= 0 && frame.stream_idx < MAX_STREAMS) { + if (frame.stream_idx < MAX_STREAMS) { frames[frame.stream_idx].push_back(frame.frame); start_pts = max(start_pts, frame.frame.pts); } @@ -340,6 +342,10 @@ void load_frame_file(const char *filename, const string &basename, unsigned file FrameOnDisk frame; frame.pts = hdr.pts(); frame.offset = ftell(fp); + if (frame.offset == -1) { + fprintf(stderr, "WARNING: %s: ftell() failed (%s).\n", filename, strerror(errno)); + break; + } frame.filename_idx = filename_idx; frame.size = hdr.file_size(); @@ -360,7 +366,11 @@ void load_frame_file(const char *filename, const string &basename, unsigned file filename, skipped_bytes); } - size_t size = ftell(fp); + off_t size = ftell(fp); + if (size == -1) { + fprintf(stderr, "WARNING: %s: ftell() failed (%s).\n", filename, strerror(errno)); + return; + } fclose(fp); db->store_frame_file(basename, size, all_frames); @@ -430,6 +440,7 @@ void load_existing_frames() // Add a gap of one second from the old frames to the new ones. start_pts += TIMEBASE; } + current_pts = start_pts; for (int stream_idx = 0; stream_idx < MAX_STREAMS; ++stream_idx) { sort(frames[stream_idx].begin(), frames[stream_idx].end(), @@ -441,62 +452,64 @@ void load_existing_frames() int record_thread_func() { - auto format_ctx = avformat_open_input_unique(global_flags.stream_source.c_str(), nullptr, nullptr); - if (format_ctx == nullptr) { - fprintf(stderr, "%s: Error opening file\n", global_flags.stream_source.c_str()); - return 1; - } + pthread_setname_np(pthread_self(), "ReceiveFrames"); - int64_t last_pts = -1; int64_t pts_offset; DB db(global_flags.working_directory + "/futatabi.db"); while (!should_quit.load()) { - AVPacket pkt; - unique_ptr pkt_cleanup( - &pkt, av_packet_unref); - av_init_packet(&pkt); - pkt.data = nullptr; - pkt.size = 0; - - // TODO: Make it possible to abort av_read_frame() (use an interrupt callback); - // right now, should_quit will be ignored if it's hung on I/O. - if (av_read_frame(format_ctx.get(), &pkt) != 0) { - break; + auto format_ctx = avformat_open_input_unique(global_flags.stream_source.c_str(), nullptr, nullptr); + if (format_ctx == nullptr) { + fprintf(stderr, "%s: Error opening file. Waiting one second and trying again...\n", global_flags.stream_source.c_str()); + sleep(1); + continue; } - // Convert pts to our own timebase. - AVRational stream_timebase = format_ctx->streams[pkt.stream_index]->time_base; - int64_t pts = av_rescale_q(pkt.pts, stream_timebase, AVRational{ 1, TIMEBASE }); + int64_t last_pts = -1; - // Translate offset into our stream. - if (last_pts == -1) { - pts_offset = start_pts - pts; - } - pts = std::max(pts + pts_offset, start_pts); - - //fprintf(stderr, "Got a frame from camera %d, pts = %ld, size = %d\n", - // pkt.stream_index, pts, pkt.size); - FrameOnDisk frame = write_frame(pkt.stream_index, pts, pkt.data, pkt.size, &db); - - post_to_main_thread([pkt, frame] { - if (pkt.stream_index == 0) { - global_mainwindow->ui->input1_display->setFrame(pkt.stream_index, frame); - } else if (pkt.stream_index == 1) { - global_mainwindow->ui->input2_display->setFrame(pkt.stream_index, frame); - } else if (pkt.stream_index == 2) { - global_mainwindow->ui->input3_display->setFrame(pkt.stream_index, frame); - } else if (pkt.stream_index == 3) { - global_mainwindow->ui->input4_display->setFrame(pkt.stream_index, frame); + while (!should_quit.load()) { + AVPacket pkt; + unique_ptr pkt_cleanup( + &pkt, av_packet_unref); + av_init_packet(&pkt); + pkt.data = nullptr; + pkt.size = 0; + + // TODO: Make it possible to abort av_read_frame() (use an interrupt callback); + // right now, should_quit will be ignored if it's hung on I/O. + if (av_read_frame(format_ctx.get(), &pkt) != 0) { + break; + } + + // Convert pts to our own timebase. + AVRational stream_timebase = format_ctx->streams[pkt.stream_index]->time_base; + int64_t pts = av_rescale_q(pkt.pts, stream_timebase, AVRational{ 1, TIMEBASE }); + + // Translate offset into our stream. + if (last_pts == -1) { + pts_offset = start_pts - pts; } - }); + pts = std::max(pts + pts_offset, start_pts); - if (last_pts != -1 && global_flags.slow_down_input) { - this_thread::sleep_for(microseconds((pts - last_pts) * 1000000 / TIMEBASE)); + //fprintf(stderr, "Got a frame from camera %d, pts = %ld, size = %d\n", + // pkt.stream_index, pts, pkt.size); + FrameOnDisk frame = write_frame(pkt.stream_index, pts, pkt.data, pkt.size, &db); + + post_to_main_thread([pkt, frame] { + global_mainwindow->display_frame(pkt.stream_index, frame); + }); + + if (last_pts != -1 && global_flags.slow_down_input) { + this_thread::sleep_for(microseconds((pts - last_pts) * 1000000 / TIMEBASE)); + } + last_pts = pts; + current_pts = pts; } - last_pts = pts; - current_pts = pts; - } + fprintf(stderr, "%s: Hit EOF. Waiting one second and trying again...\n", global_flags.stream_source.c_str()); + sleep(1); + + start_pts = last_pts + TIMEBASE; + } return 0; }