diff options
Diffstat (limited to 'modules/snapshot')
-rw-r--r-- | modules/snapshot/module.mk | 11 | ||||
-rw-r--r-- | modules/snapshot/png_vf.c | 188 | ||||
-rw-r--r-- | modules/snapshot/png_vf.h | 6 | ||||
-rw-r--r-- | modules/snapshot/snapshot.c | 90 |
4 files changed, 295 insertions, 0 deletions
diff --git a/modules/snapshot/module.mk b/modules/snapshot/module.mk new file mode 100644 index 0000000..1be53bd --- /dev/null +++ b/modules/snapshot/module.mk @@ -0,0 +1,11 @@ +# +# module.mk +# +# Copyright (C) 2010 Creytiv.com +# + +MOD := snapshot +$(MOD)_SRCS += snapshot.c png_vf.c +$(MOD)_LFLAGS += -lpng + +include mk/mod.mk diff --git a/modules/snapshot/png_vf.c b/modules/snapshot/png_vf.c new file mode 100644 index 0000000..d7f1f8a --- /dev/null +++ b/modules/snapshot/png_vf.c @@ -0,0 +1,188 @@ +/** + * @file png_vf.c Write vidframe to a PNG-file + * + * Author: Doug Blewett + * Review: Alfred E. Heggestad + */ +#define _BSD_SOURCE 1 +#include <string.h> +#include <time.h> +#include <png.h> +#include <re.h> +#include <rem.h> +#include <baresip.h> +#include "png_vf.h" + + +static char *png_filename(const struct tm *tmx, const char *name, + char *buf, unsigned int length); +static void png_save_free(png_structp png_ptr, png_byte **png_row_pointers, + int png_height); + + +int png_save_vidframe(const struct vidframe *vf, const char *path) +{ + png_byte **png_row_pointers = NULL; + png_byte *row; + const png_byte *p; + png_byte red, green, blue; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + FILE *fp = NULL; + size_t x, y; + unsigned int width = vf->size.w & ~1; + unsigned int height = vf->size.h & ~1; + unsigned int bytes_per_pixel = 3; /* RGB format */ + time_t tnow; + struct tm *tmx; + char filename_buf[64]; + struct vidframe *f2 = NULL; + int err = 0; + + tnow = time(NULL); + tmx = localtime(&tnow); + + if (vf->fmt != VID_FMT_RGB32) { + + err = vidframe_alloc(&f2, VID_FMT_RGB32, &vf->size); + if (err) + goto out; + + vidconv(f2, vf, NULL); + vf = f2; + } + + /* Initialize the write struct. */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL); + if (png_ptr == NULL) { + err = ENOMEM; + goto out; + } + + /* Initialize the info struct. */ + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + err = ENOMEM; + goto out; + } + + /* Set up error handling. */ + if (setjmp(png_jmpbuf(png_ptr))) { + err = ENOMEM; + goto out; + } + + /* Set image attributes. */ + png_set_IHDR(png_ptr, + info_ptr, + width, + height, + 8, + PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + /* Initialize rows of PNG + * bytes_per_row = width * bytes_per_pixel; + */ + png_row_pointers = png_malloc(png_ptr, + height * sizeof(png_byte *)); + + for (y = 0; y < height; ++y) { + png_row_pointers[y] = + (png_byte *) png_malloc(png_ptr, + width * sizeof(uint8_t) * + bytes_per_pixel); + } + + p = vf->data[0]; + for (y = 0; y < height; ++y) { + + row = png_row_pointers[y]; + + for (x = 0; x < width; ++x) { + + red = *p++; + green = *p++; + blue = *p++; + + *row++ = blue; + *row++ = green; + *row++ = red; + + ++p; /* skip alpha */ + } + } + + /* Write the image data. */ + fp = fopen(png_filename(tmx, path, + filename_buf, sizeof(filename_buf)), "wb"); + if (fp == NULL) { + err = errno; + goto out; + } + + png_init_io(png_ptr, fp); + png_set_rows(png_ptr, info_ptr, png_row_pointers); + png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); + + info("png: wrote %s\n", filename_buf); + + out: + /* Finish writing. */ + mem_deref(f2); + png_save_free(png_ptr, png_row_pointers, height); + png_destroy_write_struct(&png_ptr, &info_ptr); + if (fp) + fclose(fp); + + return 0; +} + + +static void png_save_free(png_structp png_ptr, png_byte **png_row_pointers, + int png_height) +{ + int y; + + /* Cleanup. */ + if (png_height == 0 || png_row_pointers == NULL) + return; + + for (y = 0; y < png_height; y++) { + png_free(png_ptr, png_row_pointers[y]); + } + png_free(png_ptr, png_row_pointers); +} + + +static char *png_filename(const struct tm *tmx, const char *name, + char *buf, unsigned int length) +{ + /* + * -2013-03-03-15-22-56.png - 24 chars + */ + if (strlen(name) + 24 >= length) { + buf[0] = '\0'; + return buf; + } + + sprintf(buf, (tmx->tm_mon < 9 ? "%s-%d-0%d" : "%s-%d-%d"), name, + 1900 + tmx->tm_year, tmx->tm_mon + 1); + + sprintf(buf + strlen(buf), (tmx->tm_mday < 10 ? "-0%d" : "-%d"), + tmx->tm_mday); + + sprintf(buf + strlen(buf), (tmx->tm_hour < 10 ? "-0%d" : "-%d"), + tmx->tm_hour); + + sprintf(buf + strlen(buf), (tmx->tm_min < 10 ? "-0%d" : "-%d"), + tmx->tm_min); + + sprintf(buf + strlen(buf), (tmx->tm_sec < 10 ? "-0%d.png" : "-%d.png"), + tmx->tm_sec); + + return buf; +} diff --git a/modules/snapshot/png_vf.h b/modules/snapshot/png_vf.h new file mode 100644 index 0000000..17660cf --- /dev/null +++ b/modules/snapshot/png_vf.h @@ -0,0 +1,6 @@ +/** + * @file png_vf.h + */ + + +int png_save_vidframe(const struct vidframe *vf, const char *path); diff --git a/modules/snapshot/snapshot.c b/modules/snapshot/snapshot.c new file mode 100644 index 0000000..b8a01de --- /dev/null +++ b/modules/snapshot/snapshot.c @@ -0,0 +1,90 @@ +/** + * @file snapshot.c Snapshot Video-Filter + * + * Copyright (C) 2010 Creytiv.com + */ +#include <string.h> +#include <re.h> +#include <rem.h> +#include <baresip.h> +#include "png_vf.h" + + +static bool flag_enc, flag_dec; + + +static int encode(struct vidfilt_enc_st *st, struct vidframe *frame) +{ + (void)st; + + if (!frame) + return 0; + + if (flag_enc) { + flag_enc = false; + png_save_vidframe(frame, "snapshot-send"); + } + + return 0; +} + + +static int decode(struct vidfilt_dec_st *st, struct vidframe *frame) +{ + (void)st; + + if (!frame) + return 0; + + if (flag_dec) { + flag_dec = false; + png_save_vidframe(frame, "snapshot-recv"); + } + + return 0; +} + + +static int do_snapshot(struct re_printf *pf, void *arg) +{ + (void)pf; + (void)arg; + + /* NOTE: not re-entrant */ + flag_enc = flag_dec = true; + + return 0; +} + + +static struct vidfilt snapshot = { + LE_INIT, "snapshot", NULL, encode, NULL, decode, +}; + + +static const struct cmd cmdv[] = { + {'o', 0, "Take video snapshot", do_snapshot }, +}; + + +static int module_init(void) +{ + vidfilt_register(&snapshot); + return cmd_register(cmdv, ARRAY_SIZE(cmdv)); +} + + +static int module_close(void) +{ + vidfilt_unregister(&snapshot); + cmd_unregister(cmdv); + return 0; +} + + +EXPORT_SYM const struct mod_export DECL_EXPORTS(snapshot) = { + "snapshot", + "vidfilt", + module_init, + module_close +}; |