summaryrefslogtreecommitdiff
path: root/src/cuttime.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cuttime.c')
-rw-r--r--src/cuttime.c190
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;
+}