#define _XOPEN_SOURCE 500 #include #include #include #include #include "video_decode.h" #include "util.h" static inline void pswap(void **p1, void **p2) { void *tmp; tmp = *p1; *p1 = *p2; *p2 = tmp; } /* print time in format: "hh:mm:ss.xxx" */ static void print_time(int64_t msec) { int hh = msec / 1000 / 60 / 60; msec -= hh * 1000 * 60 * 60; int mm = msec / 1000 / 60; msec -= mm * 1000 * 60; int ss = msec / 1000; msec -= ss * 1000; printf("%02d:%02d:%02d.%03jd", hh, mm, ss, msec); } static void start_new_szene(int64_t prev_szene_end, int64_t start) { static int prev_dts_start = 0; print_time(prev_dts_start); printf(" "); print_time(prev_szene_end - prev_dts_start); prev_dts_start = start; } static double frame_diff(struct video_frame *frame_a, struct video_frame *frame_b) { double average = 0; uint8_t *row_a = frame_a->data, *col_a = NULL; uint8_t *row_b = frame_b->data, *col_b = NULL; for (int y = 0; y < frame_a->height; ++y) { col_a = row_a; col_b = row_b; for (int x = 0; x < frame_a->width; ++x) { average += abs(*col_a - *col_b); col_a++; col_b++; } row_a += frame_a->stride; row_b += frame_b->stride; } return average / (frame_a->width * frame_a->height); } static double frame_average(struct video_frame *frame) { double average = 0; uint8_t *row = frame->data; uint8_t *col = NULL; for (int y = 0; y < frame->height; ++y) { col = row; for (int x = 0; x < frame->width; ++x) { average += *col; col++; } row += frame->stride; } return average / (frame->width * frame->height); } static void usage(void) { fprintf(stderr, "overlap [OPTIONS] FIRST_VIDEO SECOND_VIDEO\n" "\n" "OPTIONS\n" "\t-d\tprint diff for every frame\n" "\t-t\tmax duration to find overlap in milliseconds\n" "\t\t(default 60000 = 1 min)\n"); exit(EXIT_FAILURE); } int main(int argc, char **argv) { struct video_decode *first_vd; struct video_decode *second_vd; struct video_frame *cur_frame = NULL, *last_frame = NULL; // struct video_frame last_frames[5] = {0}; int ret, ch; int diff_flag = 0; int64_t timestamp = 0; int64_t duration = 60 * 1000; /* duration for searching min_diff */ /* 60 sec * 1000 msec = 1 min */ int64_t min_diff_time = 0; /* dts at overlaping frame */ double min_diff, diff = 0.0; while ((ch = getopt(argc, argv, "dt")) != -1) { switch (ch) { case 'd': diff_flag = 1; /* print diff of every frame */ break; case 't': duration = strtol(optarg, NULL, 10); break; default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc < 2) usage(); // if (argc == 2 && strtol(argv[1], NULL, 10) > 0) // timestamp = strtol(argv[1], NULL, 10); ret = video_decode_init(&first_vd, argv[0], timestamp); if (ret < 0) return -ret; /* just get last frame of move */ for (int i = 0; video_decode_get_frame(first_vd, &cur_frame) > 0; ++i) pswap((void **)&cur_frame, (void **)&last_frame); ret = video_decode_init(&second_vd, argv[1], timestamp); for (int i = 0; video_decode_get_frame(second_vd, &cur_frame) > 0; ++i){ diff = frame_diff(last_frame, cur_frame); if (i == 0 || diff <= min_diff) { min_diff = diff; min_diff_time = cur_frame->dts; } if (diff_flag) printf("%ji %f\n", cur_frame->dts, diff); if (cur_frame->dts > duration) break; } if (!diff_flag) { print_time(min_diff_time); printf("\n"); } video_decode_free_frame(&cur_frame); video_decode_free_frame(&last_frame); video_decode_uninit(&first_vd); video_decode_uninit(&second_vd); return EXIT_SUCCESS; }