From 6d7a1f124f38a4358f517437757f6f0c3fe21d8b Mon Sep 17 00:00:00 2001 From: deva Date: Sun, 19 Jun 2005 20:04:43 +0000 Subject: ImgEncoder now uses the file class for output, through jpeg_mem_dest. --- ChangeLog | 2 + TODO | 10 +- src/file.cc | 15 ++- src/file.h | 4 + src/img_encoder.cc | 247 ++++++++++++++++++++++++++++++++++------------ src/img_encoder.h | 32 +++--- src/mov_encoder.cc | 22 +++++ src/mov_encoder_writer.cc | 74 +++----------- src/server.cc | 95 +----------------- src/server_status.cc | 10 +- src/server_status.h | 10 +- 11 files changed, 274 insertions(+), 247 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5dd344f..354c586 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,8 @@ Bug Fixes: server. - Fixed server code which built up a framequeue serverside (I thought I already fixed that in last release!) + The writer must have higher priority than the encoders, otherwise + it can't follow up on the writing. ======================================= Juni 16 2005 - MIaV version 0.2.5 diff --git a/TODO b/TODO index 141a468..03ed895 100644 --- a/TODO +++ b/TODO @@ -15,8 +15,6 @@ http://encyclopedia.laborlawtalk.com/YUV_4:2:0 open64 ? -Split files at some given (in config file) point? - ========================================================================== @@ -50,7 +48,7 @@ Mainwindow: shot on the server. [ ] - Test it. [x] - Show recordtime in client window. - [ ] - Clear / update taskbar. + [x] - Clear / update taskbar. [ ] - Make new messagebox when asking to save movie. (Save, Delete, Cancel, Save in one week) [x] - Make "clear" button in mainwindow, to remove last patient, before @@ -106,7 +104,7 @@ MovEncoder: (Best quality less than 22mb/s realtime encoded) [x] - Multithread encoding, for multi cpu support. [ ] - libFame frames have no timecodes!!! - [ ] - Files turning too big (>2gb) must automatically close and + [x] - Files turning too big (>2gb) must automatically close and conitnue in another file. Main: @@ -118,7 +116,7 @@ Main: [x] - Permissions on server file writing. Files: u+wr g+r a+x - Directories: u+wrx g+rx a+rx. [ ] - Permissions on server file writing to be read from config. - [ ] - Open med create unique + [x] - Open med create unique ========================================================================== TASKS (common) @@ -154,7 +152,7 @@ ErrorObject: [x] - Make it a superclass. [x] - Create a textmode version subclass (for the server). [x] - Create a QT version subclass (callback to mainwindow with messagebox). - [ ] - Append to log, whenever error occur. + [x] - Append to log, whenever error occur. FFMpegWrapper: [%] - Make it.(FFMPEG is on its way out of the project) diff --git a/src/file.cc b/src/file.cc index 2ba20bb..49b9bb5 100644 --- a/src/file.cc +++ b/src/file.cc @@ -31,6 +31,9 @@ /* * $Log$ + * Revision 1.6 2005/06/19 20:04:43 deva + * ImgEncoder now uses the file class for output, through jpeg_mem_dest. + * * Revision 1.5 2005/06/19 11:44:14 deva * Cleaned up a log of logging. * Fixed server queue (shouldn't happen). @@ -61,19 +64,16 @@ #include #include -#include - #include - File::File(char *fn, char* ext, Info *i) { char path[256]; info = i; - filename = (char*)malloc(strlen(fn) + 1); - extension = (char*)malloc(strlen(ext) + 1); + filename = new char[strlen(fn) + 1]; + extension = new char[strlen(ext) + 1]; strcpy(filename, fn); strcpy(extension, ext); @@ -98,8 +98,8 @@ File::~File() { close(fd); - free(filename); - free(extension); + delete filename; + delete extension; } int File::Open() @@ -179,4 +179,3 @@ int File::createPath(char* path) return 0; } - diff --git a/src/file.h b/src/file.h index 6326528..3faecb5 100644 --- a/src/file.h +++ b/src/file.h @@ -31,6 +31,9 @@ /* * $Log$ + * Revision 1.3 2005/06/19 20:04:43 deva + * ImgEncoder now uses the file class for output, through jpeg_mem_dest. + * * Revision 1.2 2005/06/13 20:38:19 deva * Added some logfile code. * Enhanced the file object... now ready to hook into mov_encoder @@ -46,6 +49,7 @@ #define __MIAV_FILE_H__ #include "info.h" +#include #include using namespace std; diff --git a/src/img_encoder.cc b/src/img_encoder.cc index c5cc58b..2412520 100644 --- a/src/img_encoder.cc +++ b/src/img_encoder.cc @@ -39,6 +39,9 @@ /* * $Log$ + * Revision 1.10 2005/06/19 20:04:43 deva + * ImgEncoder now uses the file class for output, through jpeg_mem_dest. + * * Revision 1.9 2005/05/26 12:48:36 deva * *** empty log message *** * @@ -62,91 +65,211 @@ #include #include -ImgEncoder::ImgEncoder() +ImgEncoder::ImgEncoder(const char* cpr, Info *i) { + info = i; + + // Create path and filename + char fname[256]; + string *server_root; + char birthmonth[3]; + char date[32]; + + // Get server root + server_root = config->readString("server_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); + + sprintf(fname, "%s/%s/%s/%s-%s-", server_root->c_str(), birthmonth, cpr, cpr, date); + + file = new File(fname, "jpg", info); } + ImgEncoder::~ImgEncoder() { + delete file; } -void ImgEncoder::encode(Frame *dvframe, - char *filename, - int quality) + +void ImgEncoder::encode(Frame *dvframe, int quality) { - // Append suffix.. - char fname[256]; - sprintf(fname, "%s.jpg", filename); - unsigned char rgb[720*576*4]; getRGB(dvframe, rgb); - writeJPEGFile(fname, quality, (JSAMPLE*)rgb, 720, 576); + writeJPEGFile(quality, (JSAMPLE*)rgb, 720, 576); } -/////////////////////////////////////////////////////////////////////////////////////////// - -void ImgEncoder::writeJPEGFile(char *filename, - int quality, - JSAMPLE * image_buffer, // Points to large array of R,G,B-order data - int image_width, // Number of columns in image - int image_height // Number of rows in image -) + +#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently ?? size */ + +/* Expanded data destination object for stdio output */ +typedef struct { + struct jpeg_destination_mgr pub; /* public fields */ + + JOCTET * outbuff; /* target buffer */ + size_t * size; +} mem_destination_mgr; + +typedef mem_destination_mgr * mem_dest_ptr; + +/* + * Initialize destination --- called by jpeg_start_compress + * before any data is actually written. + */ +void init_destination (j_compress_ptr cinfo) { - struct jpeg_compress_struct cinfo; - struct jpeg_error_mgr jerr; - - FILE * outfile; // target file - JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s] - int row_stride; // physical row width in image buffer - - // Step 1: allocate and initialize JPEG compression object - cinfo.err = jpeg_std_error(&jerr); - jpeg_create_compress(&cinfo); - - // Step 2: specify data destination (eg, a file) - if ((outfile = fopen(filename, "wb")) == NULL) { - fprintf(stderr, "can't open %s\n", filename); - exit(1); - } - jpeg_stdio_dest(&cinfo, outfile); + mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; + + *dest->size = 0; + dest->pub.next_output_byte = dest->outbuff; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; +} + +/* + * Terminate destination --- called by jpeg_finish_compress + * after all data has been written. Usually needs to flush buffer. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ +void term_destination (j_compress_ptr cinfo) +{ + mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; + size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + + /* Write any data remaining in the buffer */ + if (datacount > 0) { + dest->outbuff+=datacount; + *dest->size+=datacount; + } +} + +/* + * Empty the output buffer --- called whenever buffer fills up. + * + * In typical applications, this should write the entire output buffer + * (ignoring the current state of next_output_byte & free_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been dumped. + * + * In applications that need to be able to suspend compression due to output + * overrun, a FALSE return indicates that the buffer cannot be emptied now. + * In this situation, the compressor will return to its caller (possibly with + * an indication that it has not accepted all the supplied scanlines). The + * application should resume compression after it has made more room in the + * output buffer. Note that there are substantial restrictions on the use of + * suspension --- see the documentation. + * + * When suspending, the compressor will back up to a convenient restart point + * (typically the start of the current MCU). next_output_byte & free_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point will be regenerated after resumption, so do not + * write it out when emptying the buffer externally. + */ +boolean empty_output_buffer (j_compress_ptr cinfo) +{ + mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; + + dest->outbuff+=OUTPUT_BUF_SIZE; + *dest->size+=OUTPUT_BUF_SIZE; + + dest->pub.next_output_byte = dest->outbuff; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + + return TRUE; +} + +/* + * Prepare for output to a memory buffer. + . The caller must have already allocated the buffer, and is responsible + * for closing it after finishing compression. + */ +void jpeg_mem_dest (j_compress_ptr cinfo, char * outbuff, size_t * size) +{ + mem_dest_ptr dest; + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same file without re-executing jpeg_stdio_dest. + * This makes it dangerous to use this manager and a different destination + * manager serially with the same JPEG object, because their private object + * sizes may be different. Caveat programmer. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + sizeof(mem_destination_mgr)); + } + + dest = (mem_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; + dest->outbuff = (JOCTET *)outbuff; + dest->size = (size_t *)size; +} + +void ImgEncoder::writeJPEGFile(int quality, JSAMPLE * image_buffer, int image_width, int image_height) +{ + 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; - // Step 3: set parameters for compression - 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 + JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s] + int row_stride; // physical row width in image buffer - //typedef enum { - // JCS_UNKNOWN, // error/unspecified - // JCS_GRAYSCALE, // monochrome - // JCS_RGB, // red/green/blue - // JCS_YCbCr, // Y/Cb/Cr (also known as YUV) - // JCS_CMYK, // C/M/Y/K - // JCS_YCCK // Y/Cb/Cr/K - //} J_COLOR_SPACE; + // Step 1: allocate and initialize JPEG compression object + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); - cinfo.in_color_space = JCS_RGB; // colorspace of input image + // Step 2: specify data destination (eg, a file) + //jpeg_stdio_dest(&cinfo, file->getFP()); + jpeg_mem_dest(&cinfo, jpeg_output_buffer, &buffersize); - jpeg_set_defaults(&cinfo); + // Step 3: set parameters for compression + 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_quality(&cinfo, quality, TRUE); // limit to baseline-JPEG values + jpeg_set_defaults(&cinfo); - // Step 4: Start compressor - jpeg_start_compress(&cinfo, TRUE); + jpeg_set_quality(&cinfo, quality, TRUE); // limit to baseline-JPEG values - // Step 5: while (scan lines remain to be written) - row_stride = image_width * 3; // JSAMPLEs per row in image_buffer + // Step 4: Start compressor + jpeg_start_compress(&cinfo, TRUE); - 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); - } + // Step 5: while (scan lines remain to be written) + row_stride = image_width * 3; // JSAMPLEs per row in image_buffer - // Step 6: Finish compression - jpeg_finish_compress(&cinfo); - fclose(outfile); + 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); + } - // Step 7: release JPEG compression object - jpeg_destroy_compress(&cinfo); + // Step 6: Finish compression + jpeg_finish_compress(&cinfo); + + // Step 7: release JPEG compression object + jpeg_destroy_compress(&cinfo); + + info->info("JPEG buffersize: %d", buffersize); + file->Write(jpeg_output_buffer, buffersize); + delete jpeg_output_buffer; } void ImgEncoder::getRGB(Frame *frame, unsigned char *rgb) diff --git a/src/img_encoder.h b/src/img_encoder.h index 4ffec57..eb702b2 100644 --- a/src/img_encoder.h +++ b/src/img_encoder.h @@ -38,6 +38,9 @@ /* * $Log$ + * Revision 1.8 2005/06/19 20:04:43 deva + * ImgEncoder now uses the file class for output, through jpeg_mem_dest. + * * Revision 1.7 2005/05/07 10:25:34 deva * * Removed ffmpeg code from img_encoder and corrected decoding errors in mov_encoder @@ -69,33 +72,26 @@ extern "C" { #endif } +#include "info.h" +#include "file.h" + #define VIDEO_BUFFER_SIZE (1024*1024) // FIXME: One size fits all... +#define JPEG_HEADER_PAD 500 class ImgEncoder { - public: - ImgEncoder(); +public: + ImgEncoder(const char* cpr, Info *info); ~ImgEncoder(); - void encode(Frame *frame, char* filename, int quality); - void writeJPEGFile(char *filename, - int quality, + void encode(Frame *frame, int quality); + void writeJPEGFile(int quality, JSAMPLE * image_buffer, // Points to large array of R,G,B-order data int image_width, // Number of columns in image int image_height); // Number of rows in image - private: +private: + File *file; + Info *info; void getRGB(Frame *frame, unsigned char *rgb); - /* - // Decoder - AVFormatContext *dfc; - AVCodecContext *dcc; - - // Encoder - AVFormatContext *efc; - AVCodecContext *ecc; - AVPacket epkt; - unsigned char *video_buffer; - // AVPacket pkt; - */ }; #endif /*__RTVIDEOREC_IMGENCODER_H*/ diff --git a/src/mov_encoder.cc b/src/mov_encoder.cc index b31e1c9..3aa7a49 100644 --- a/src/mov_encoder.cc +++ b/src/mov_encoder.cc @@ -39,6 +39,9 @@ /* * $Log$ + * Revision 1.32 2005/06/19 20:04:43 deva + * ImgEncoder now uses the file class for output, through jpeg_mem_dest. + * * Revision 1.31 2005/06/19 11:44:14 deva * Cleaned up a log of logging. * Fixed server queue (shouldn't happen). @@ -122,6 +125,9 @@ #include +// For nice +#include + #include "miav_config.h" #include "debug.h" @@ -385,6 +391,13 @@ void MovEncoder::encode_audio(Frame *dvframe) void MovEncoder::thread_main() { info->info("MovEncoder thread is running."); + static volatile int test = 0; + int outsize = 0; + int insize = 0; + + // Run with slightly lower priority than MovEncoderWriter + nice(1); + FrameVector *item; Frame *in_frame; @@ -397,6 +410,9 @@ void MovEncoder::thread_main() pthread_mutex_lock(input_mutex); item = inputqueue->front(); inputqueue->pop(); + + insize = inputqueue->size(); + pthread_mutex_unlock(input_mutex); // Unlock input mutex @@ -411,12 +427,18 @@ void MovEncoder::thread_main() // Lock output mutex pthread_mutex_lock(output_mutex); outputqueue->push(out_frame); + + outsize = outputqueue->size(); + pthread_mutex_unlock(output_mutex); // Unlock output mutex } delete item; + test++; + if(test % (25 * 24) == 0) info->info("Input pool size: %d, output pool size: %d", insize, outsize); + // Kick frame writer sem_post(output_sem); diff --git a/src/mov_encoder_writer.cc b/src/mov_encoder_writer.cc index a10d671..1c0fe1b 100644 --- a/src/mov_encoder_writer.cc +++ b/src/mov_encoder_writer.cc @@ -31,6 +31,9 @@ /* * $Log$ + * Revision 1.7 2005/06/19 20:04:43 deva + * ImgEncoder now uses the file class for output, through jpeg_mem_dest. + * * Revision 1.6 2005/06/16 21:28:57 deva * Rewrote thread object * Fixed bug in mov_encoder (pushed read_sem too many times, whihc lead to @@ -131,88 +134,43 @@ void MovEncoderWriter::thread_main() while(running) { sem_wait(sem); + // int poolsize; + // Lock output mutex pthread_mutex_lock(mutex); frame = queue->top(); if(frame && frame->number == frame_number) queue->pop(); + // poolsize = queue->size(); pthread_mutex_unlock(mutex); // Unlock output mutex + int wrote = 0; while(frame && (frame->number == frame_number)) { + int ret; ret = file->Write(frame->data, frame->size); + frame_number++; + wrote ++; delete frame; - if(ret == -1) return; + if(ret == -1) { + info->error("File write returned -1."); + return; + } - frame_number++; - // Lock output mutex pthread_mutex_lock(mutex); frame = queue->top(); if(frame && frame->number == frame_number) queue->pop(); + // poolsize = queue->size(); pthread_mutex_unlock(mutex); // Unlock output mutex } - } - - info->info("MovEncoderWriter::stop"); -} - -/* -void MovEncoderWriter::thread_main() -{ - unsigned int howdeep = 0; - info->info("MovEncoderWriter::run"); - - Frame *frame; - - while(running) { - sem_wait(sem); - howdeep++; - - // Lock output mutex - pthread_mutex_lock(mutex); - if(queue->size() == 0) { - info->warn("1MovEncoderWriter encountered an empty queue (This shouldn't happen)."); - // Unlock output mutex - pthread_mutex_unlock(mutex); - continue; - } - frame = queue->top(); - if(frame->number == frame_number) queue->pop(); - pthread_mutex_unlock(mutex); - // Unlock output mutex - - while((frame->number == frame_number) && howdeep) { - howdeep--; - int ret; - - ret = file->Write(frame->data, frame->size); - - delete frame; - - if(ret == -1) return; - - frame_number++; - - // Lock output mutex - pthread_mutex_lock(mutex); - if(queue->size() == 0) { - info->warn("2MovEncoderWriter encountered an empty queue (This shouldn't happen)."); - pthread_mutex_unlock(mutex); - continue; - } - frame = queue->top(); - if(frame->number == frame_number) queue->pop(); - pthread_mutex_unlock(mutex); - // Unlock output mutex - } + // info->info("Wrote %d frames, pool size %d - exp: %d", wrote, poolsize, frame_number); } info->info("MovEncoderWriter::stop"); } -*/ diff --git a/src/server.cc b/src/server.cc index e6a6ff7..35dbb9d 100644 --- a/src/server.cc +++ b/src/server.cc @@ -31,6 +31,9 @@ /* * $Log$ + * Revision 1.25 2005/06/19 20:04:43 deva + * ImgEncoder now uses the file class for output, through jpeg_mem_dest. + * * Revision 1.24 2005/06/19 11:44:14 deva * Cleaned up a log of logging. * Fixed server queue (shouldn't happen). @@ -116,94 +119,6 @@ #include "dv.h" -void saveFrameAsImage(char* cpr, Frame *f) -{ - ImgEncoder imgenc; - struct tm *ltime; - time_t t = time(NULL); - FILE *fp; - int cnt = 0; - char fname[256]; - char birthmonth[3]; - char date[9]; - - string *root = config->readString("server_root"); - - // Test for server root writeability - sprintf(fname, "%s/miavtemp.tmp%d", (char*)root->c_str(), rand()); - fp = fopen(fname, "w"); - if(!fp) { - int r = rand(); - fprintf(stderr, "MIaV does not have write access to the server root [%s]\n", root->c_str()); - fprintf(stderr, "Redirecting output to [/tmp/miav-%d.jpg]\n", r); - sprintf(fname, "/tmp/miav-%d", r); - imgenc.encode(f, fname, 100); // Quality is between 0...100, where 100 is best. - return; - } - fclose(fp); - unlink(fname); - - // Check for cpr length correctness - if(strlen(cpr) != 11) { - int r = rand(); - fprintf(stderr, "Illigal CPR, it must have length 11, it had length %d\n", strlen(cpr)); - fprintf(stderr, "Redirecting output to [/tmp/miav-%d.jpg]\n", r); - sprintf(fname, "/tmp/miav-%d", r); - imgenc.encode(f, fname, 100); // Quality is between 0...100, where 100 is best. - return; - } - - // Copy the bytes representing the birth month from the cpr - // [dd][mm][yy]-[nn][nn] - strncpy(birthmonth, &cpr[2], 2); - birthmonth[2] = 0; - - // Create folder named birthmonth in server root - sprintf(fname, "%s/%s", root->c_str(), birthmonth); - if(!mkdir(fname, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH | S_IROTH) == -1 && errno != EEXIST) { - int r = rand(); - fprintf(stderr, "Not possible to create subfolder %s\n", fname); - fprintf(stderr, "Redirecting output to [/tmp/miav-%d.jpg]\n", r); - sprintf(fname, "/tmp/miav-%d", r); - imgenc.encode(f, fname, 100); // Quality is between 0...100, where 100 is best. - return; - } - - // Create folder named cpr in serverroot/birthmonth - sprintf(fname, "%s/%s/%s", root->c_str(), birthmonth, cpr); - if(!mkdir(fname, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH | S_IROTH) == -1 && errno != EEXIST) { - int r = rand(); - fprintf(stderr, "Not possible to create subfolder %s\n", fname); - fprintf(stderr, "Redirecting output to [/tmp/miav-%d.jpg]\n", r); - sprintf(fname, "/tmp/miav-%d", r); - imgenc.encode(f, fname, 100); // Quality is between 0...100, where 100 is best. - return; - } - - // Create date (today) in [yyyy][mm][dd] - ltime = localtime(&t); - sprintf(date, "%.4d%.2d%.2d", - ltime->tm_year + 1900, - ltime->tm_mon, - ltime->tm_mday); - - // Create filename: [serverroot]/[birthmonth]/[cpr]/[cpr]-[date]-[cnt].mpg - sprintf(fname, "%s/%s/%s/%s-%s-%.3d.jpg", root->c_str(), birthmonth, cpr, cpr, date, cnt); - - // test filename-[cnt] for existamce cnt++ until not existing. - fp = fopen(fname, "r"); - while(fp) { - fclose(fp); - cnt++; - sprintf(fname, "%s/%s/%s/%s-%s-%.3d.jpg", root->c_str(), birthmonth, cpr, cpr, date, cnt); - fp = fopen(fname, "r"); - } - sprintf(fname, "%s/%s/%s/%s-%s-%.3d", root->c_str(), birthmonth, cpr, cpr, date, cnt); - - fprintf(stderr, "Success - using filename: [%s.jpg]\n", fname); fflush(stderr); - imgenc.encode(f, fname, 100); // Quality is between 0...100, where 100 is best. -} - void newConnection(Socket *socket, Info *info) { char cpr[256]; @@ -245,11 +160,11 @@ void newConnection(Socket *socket, Info *info) if(h.header.h_data.snapshot) { if(freeze_frame) { - saveFrameAsImage(cpr, freeze_frame); + ImgEncoder(cpr, info).encode(freeze_frame, 100); delete freeze_frame; freeze_frame = NULL; } else { - saveFrameAsImage(cpr, frame); + ImgEncoder(cpr, info).encode(frame, 100); } } diff --git a/src/server_status.cc b/src/server_status.cc index e65cef2..2b2395c 100644 --- a/src/server_status.cc +++ b/src/server_status.cc @@ -31,6 +31,9 @@ /* * $Log$ + * Revision 1.10 2005/06/19 20:04:43 deva + * ImgEncoder now uses the file class for output, through jpeg_mem_dest. + * * Revision 1.9 2005/06/19 11:44:14 deva * Cleaned up a log of logging. * Fixed server queue (shouldn't happen). @@ -76,7 +79,7 @@ ServerStatus::ServerStatus(Info *i) gettimeofday(&time, NULL); - frame = 0; + interval = 0; } ServerStatus::~ServerStatus() @@ -95,8 +98,9 @@ void ServerStatus::checkPoint() gettimeofday(&time, NULL); - frame++; - if(frame % UPD == 0) { + interval += frametime[0]; + if(interval > UPD) { + interval = 0; double total = 0.0; for(int cnt = 0; cnt < BUFFERSIZE; cnt++) { total += (double)frametime[cnt]; diff --git a/src/server_status.h b/src/server_status.h index 58de61c..73b8ecb 100644 --- a/src/server_status.h +++ b/src/server_status.h @@ -31,6 +31,9 @@ /* * $Log$ + * Revision 1.5 2005/06/19 20:04:43 deva + * ImgEncoder now uses the file class for output, through jpeg_mem_dest. + * * Revision 1.4 2005/06/19 11:44:14 deva * Cleaned up a log of logging. * Fixed server queue (shouldn't happen). @@ -52,8 +55,11 @@ #include +// How many steps to do avarage calculation over. #define BUFFERSIZE 100 -#define UPD 1500 + +// Interval in us (microseconds) +#define UPD 60 * 1000 * 1000 // 1 minute class ServerStatus { public: @@ -63,7 +69,7 @@ public: void checkPoint(); private: - int frame; + long long interval; Info *info; unsigned int frametime[BUFFERSIZE]; struct timeval time; -- cgit v1.2.3