/* -*- 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 #include #include extern "C" { #include } #include #include "jpeg_mem_dest.h" #include "miav_config.h" ImgEncoder::ImgEncoder(const char* cpr) { // Create path and filename char fname[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(fname, "%s/%s/%s/%s-%s-", server_root->c_str(), birthmonth, encrypted_cpr, cpr, date); file = new File(fname, "jpg"); } ImgEncoder::~ImgEncoder() { delete file; } 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); DEBUG(jpeg, "JPEG buffersize: %d", (int)buffersize); file->Write(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); }