summaryrefslogtreecommitdiff
path: root/miavd/img_encoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'miavd/img_encoder.cc')
-rw-r--r--miavd/img_encoder.cc232
1 files changed, 232 insertions, 0 deletions
diff --git a/miavd/img_encoder.cc b/miavd/img_encoder.cc
new file mode 100644
index 0000000..b326749
--- /dev/null
+++ b/miavd/img_encoder.cc
@@ -0,0 +1,232 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * img_encoder.cc
+ *
+ * Mon Nov 15 19:45:07 CET 2004
+ * Copyright 2004 Bent Bisballe
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * Originally from:
+ * RTVideoRec Realtime video recoder and encoder for Linux
+ *
+ * Copyright (C) 2004 B. Stultiens
+ * Copyright (C) 2004 Koen Otter and Glenn van der Meyden
+ */
+
+/*
+ * This file is part of MIaV.
+ *
+ * MIaV is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MIaV is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MIaV; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "img_encoder.h"
+#include <stdio.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <info.h>
+
+#include "debug.h"
+
+extern "C" {
+#include <jpeglib.h>
+}
+
+#include "jpeg_mem_dest.h"
+
+// Use libdv
+#include <libdv/dv.h>
+#include <libdv/dv_types.h>
+
+ImgEncoder::ImgEncoder(const char* cpr)
+{
+ // Create path and filename
+ char filename[256];
+ string *server_root;
+ char birthmonth[3];
+ char date[32];
+ char encrypted_cpr[32];
+
+ // Get server root
+ server_root = config->readString("server_image_root");
+
+ // Copy the bytes representing the birth month from the cpr
+ // [dd][mm][yy]-[nn][nn]
+ strncpy(birthmonth, &cpr[2], 2);
+ birthmonth[2] = 0;
+
+ // Create date (today) in [yyyy][mm][dd]
+ struct tm *ltime;
+ time_t t = time(NULL);
+ ltime = localtime(&t);
+ sprintf(date, "%.4d%.2d%.2d",
+ ltime->tm_year + 1900,
+ ltime->tm_mon,
+ ltime->tm_mday);
+
+ // Create 'encrypted' cpr, reverse numbers, skip month, and subtract from 9
+ // [d1][d2][m1][m2][y1][y2]-[n1][n2][n3][n4]
+ // =>
+ // [9-n4][9-n3][9-n2][9-n1][9-y2][9-y1][9-d2][9-d1]
+ memset(encrypted_cpr, 0, sizeof(encrypted_cpr));
+ int p = strlen(cpr) - 1;
+ int cnt = 0;
+ while(p) {
+ encrypted_cpr[cnt] = cpr[p];
+ p--;
+ if(p == 2) p--;
+ if(cpr[p] == '-' || p == 3) p--;
+ cnt++;
+ }
+
+ sprintf(filename, "%s/%s/%s/%s-%s-", server_root->c_str(), birthmonth, encrypted_cpr, cpr, date);
+ char extension[] = "jpg";
+
+ //
+ // Open unique file.
+ //
+ fd = -1;
+ int num = 0;
+ char buf[512];
+
+ while(fd == -1 && num < 999) {
+ sprintf(buf, "%s%.3d.%s", filename, num, extension);
+
+ // Try to open exclusively, fails if file already exists.
+ fd = open(buf, O_CREAT | O_WRONLY | O_ASYNC | O_EXCL, //| O_LARGEFILE
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+ if(fd == -1) {
+ switch(errno) {
+ case EEXIST:
+ num ++;
+ break;
+ default:
+ MIaV::info->error("Something is wrong with the path [%s] - %s!", filename, strerror(errno));
+ return;
+ }
+ }
+ }
+
+ MIaV::info->info("Writing screenshot to file: %s", buf);
+
+}
+
+
+ImgEncoder::~ImgEncoder()
+{
+ if(fd != -1) close(fd);
+}
+
+
+void ImgEncoder::encode(Frame *dvframe, int quality)
+{
+ unsigned char rgb[720*576*4];
+
+ getRGB(dvframe, rgb);
+ writeJPEGFile(quality, rgb, 720, 576);
+}
+
+
+void ImgEncoder::writeJPEGFile(int quality, unsigned char *rgb, int image_width, int image_height)
+{
+ JSAMPLE *image_buffer = (JSAMPLE*)rgb;
+
+ size_t buffersize = (image_width * image_height * 3) + JPEG_HEADER_PAD;
+ char *jpeg_output_buffer = new char [buffersize];
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+
+ JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s]
+ int row_stride; // physical row width in image buffer
+
+ // Allocate and initialize JPEG compression object
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+
+ // Specify data destination (see jpeg_mem_dest)
+ jpeg_mem_dest(&cinfo, jpeg_output_buffer, &buffersize);
+
+ // Set compression parameters
+ cinfo.image_width = image_width; // image width and height, in pixels
+ cinfo.image_height = image_height;
+ cinfo.input_components = 3; // # of color components per pixel
+ cinfo.in_color_space = JCS_RGB; // colorspace of input image
+
+ jpeg_set_defaults(&cinfo);
+
+ jpeg_set_quality(&cinfo, quality, TRUE); // limit to baseline-JPEG values
+
+ // Start compressor
+ jpeg_start_compress(&cinfo, TRUE);
+
+ // While (scan lines remain to be written)
+ row_stride = image_width * 3; // JSAMPLEs per row in image_buffer
+
+ while (cinfo.next_scanline < cinfo.image_height) {
+ row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
+ (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
+ }
+
+ // Finish compression
+ jpeg_finish_compress(&cinfo);
+
+ // Release JPEG compression object
+ jpeg_destroy_compress(&cinfo);
+
+ // MIaV::info->info("JPEG buffersize: %d", buffersize);
+
+ if(fd != -1) write(fd, jpeg_output_buffer, buffersize);
+
+ delete jpeg_output_buffer;
+}
+
+void ImgEncoder::getRGB(Frame *frame, unsigned char *rgb)
+{
+ unsigned char *pixels[3];
+ int pitches[3];
+
+ pixels[ 0 ] = rgb;
+ pixels[ 1 ] = NULL;
+ pixels[ 2 ] = NULL;
+
+ pitches[ 0 ] = 720 * 3;
+ pitches[ 1 ] = 0;
+ pitches[ 2 ] = 0;
+
+ dv_decoder_t *decoder = dv_decoder_new(FALSE/*this value is unused*/, FALSE, FALSE);
+ decoder->quality = DV_QUALITY_BEST;
+
+ dv_parse_header(decoder, frame->data);
+
+ decoder->system = e_dv_system_625_50; // PAL lines, PAL framerate
+ decoder->sampling = e_dv_sample_422; // 4 bytes y, 2 bytes u, 2 bytes v
+ decoder->std = e_dv_std_iec_61834;
+ decoder->num_dif_seqs = 12;
+
+ // libdv img decode to rgb
+ dv_decode_full_frame(decoder,
+ frame->data,
+ e_dv_color_rgb,
+ pixels,
+ pitches);
+
+ dv_decoder_free(decoder);
+}