#define _XOPEN_SOURCE 700 #include #include #include #include #include #include "video_decode.h" #include "util.h" int pgm_read(char *filename, unsigned char **buf, int *xsize, int *ysize) { FILE *f = NULL; unsigned char *b = NULL; int width, height; ssize_t n; f = fopen(filename, "r"); if (f == NULL) return -1; if (fscanf(f, "P5\n%d %d\n255\n", &width, &height) == 0) goto fail; if (width * height <= 0) goto fail; if ((b = malloc(width * height)) == NULL) goto fail; if ((n = fread(b, 1, width * height, f)) == 0 || n != width * height) goto fail; fclose(f); *buf = b; *xsize = width; *ysize = height; return 0; fail: if (f) fclose(f); if (b) free(b); return -1; } int pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, char *filename) { FILE *f; int i; f = fopen(filename, "w"); if (f == NULL) return -1; fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255); for(i = 0; i < ysize; i++) fwrite(buf + i * wrap, 1, xsize, f); fclose(f); return 0; } void frame_mix(struct video_frame *frame_a, struct video_frame *frame_b) { 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) { if (x > frame_a->width / 2) *col_a = *col_b; col_a++; col_b++; } row_a += frame_a->stride; row_b += frame_b->stride; } } 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); } 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); } /* print time in format: "hh:mm:ss.xxx" */ 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.%03" PRId64, hh, mm, ss, msec); } int sobel(struct video_frame *frame, unsigned char **d) { unsigned char *data; unsigned char *p = frame->data; int x,y; int Yx, Yy, Y; data = malloc(frame->width * frame->height); if (data == NULL) return -1; for (y = 1; y < frame->height-1; ++y) { for (x = 1; x < frame->width-1; ++x) { Yx = (+1 * p[(y-1) * frame->stride + (x-1)] -1 * p[(y-1) * frame->stride + (x+1)] +2 * p[(y ) * frame->stride + (x-1)] -2 * p[(y ) * frame->stride + (x+1)] +1 * p[(y+1) * frame->stride + (x-1)] -1 * p[(y+1) * frame->stride + (x+1)]); Yx = abs(Yx); Yy = (+1 * p[(y-1) * frame->stride + (x-1)] +2 * p[(y-1) * frame->stride + (x )] +1 * p[(y-1) * frame->stride + (x+1)] -1 * p[(y+1) * frame->stride + (x-1)] -2 * p[(y+1) * frame->stride + (x )] -1 * p[(y+1) * frame->stride + (x+1)]); Yy = abs(Yy); Y = (Yx > Yy ? Yx : Yy) / 4; if (Y > 255) Y = 255; data[y * frame->width + x] = Y; } } *d = data; return 0; }