diff options
Diffstat (limited to 'src/cuttime.c')
-rw-r--r-- | src/cuttime.c | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/src/cuttime.c b/src/cuttime.c new file mode 100644 index 0000000..1b0fa3d --- /dev/null +++ b/src/cuttime.c @@ -0,0 +1,190 @@ +#define _XOPEN_SOURCE 500 +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <unistd.h> + +#include "video_decode.h" +#include "util.h" + +static inline void +pswap(void **p1, void **p2) +{ + void *tmp; + + tmp = *p1; + *p1 = *p2; + *p2 = tmp; +} + +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, + "advtime [-adfs] FILE\n" + "\n" + "OPTIONS\n" + "\t-a\tcalculate average color of a frame\n" + "\t-d\tcalculate difference betweenprev and next frame\n" + "\t-f\tprint frame number\n" + "\t-s\tsave frame from detected cut\n"); + + exit(EXIT_FAILURE); +} + +int +main(int argc, char **argv) +{ + struct video_decode *vd; + struct video_frame *frame_a = NULL, *frame_b = NULL; + int ret, ch; + int diff_flag = 0, average_flag = 0, frame_flag = 0, showcut_flag = 0; + int64_t timestamp = 0; + double diff = 0.0, old_diff = 0.0; + char filename[BUFSIZ]; + + while ((ch = getopt(argc, argv, "adfs")) != -1) { + switch (ch) { + case 'a': + average_flag = 1; + break; + case 'd': + diff_flag = 1; + break; + case 'f': + frame_flag = 1; + break; + case 's': + showcut_flag = 1; + break; + default: + usage(); + /* NOTREACHED */ + } + } + argc -= optind; + argv += optind; + + if (argc < 1) + usage(); + + if (argc == 2 && strtol(argv[1], NULL, 10) > 0) + timestamp = strtol(argv[1], NULL, 10); + + ret = video_decode_init(&vd, argv[0], timestamp); + if (ret < 0) + return -ret; + + ret = video_decode_get_frame(vd, &frame_a); + if (ret < 0) + return -ret; + + for (int i = 0; video_decode_get_frame(vd, &frame_b) > 0; ++i) { + + if (frame_flag) /* print frame number */ + printf("%d\t", i); + + if (average_flag) /* print frame average */ + printf("%f", frame_average(frame_a)); + + if (average_flag && diff_flag) + printf("\t"); + + if (diff_flag) { + diff = frame_diff(frame_a, frame_b); +// printf("%f", diff); +// printf("\t%f", (diff - old_diff)); + old_diff = diff; + } + + if (diff > 40.0) { + start_new_szene(frame_a->dts, frame_b->dts); + + if (!frame_flag && !average_flag) { + printf("\n"); + fflush(stdout); + } + + if (showcut_flag == 1) { + snprintf(filename, BUFSIZ, "img/%04i.pgm", i); + frame_mix(frame_a, frame_b); + + if (pgm_save(frame_a->data, frame_a->stride, + frame_a->width, frame_a->height, + filename) < 0) + exit(EXIT_FAILURE); + } + } + + if (frame_flag || average_flag) { + printf("\n"); + fflush(stdout); + } + + pswap((void **)&frame_a, (void **)&frame_b); + } + + if (diff_flag) { + /* acutally we just finalize the last frame here */ + start_new_szene(frame_a->dts, 0); + printf("\n"); + } + + video_decode_free_frame(&frame_a); + if (frame_b) + video_decode_free_frame(&frame_b); + video_decode_uninit(&vd); + return EXIT_SUCCESS; +} |