00001 #include <errno.h>
00002 #include <iostream>
00003
00004 #include "FCam/AsyncFile.h"
00005 #include "FCam/Frame.h"
00006 #include "FCam/processing/JPEG.h"
00007 #include "FCam/processing/DNG.h"
00008 #include "FCam/processing/Dump.h"
00009
00010 #include "Debug.h"
00011
00012 using namespace std;
00013
00014 namespace FCam {
00015 void *launch_async_file_writer_thread_(void *arg) {
00016 AsyncFileWriter *d = (AsyncFileWriter *)arg;
00017 d->run();
00018 d->running = false;
00019 pthread_exit(NULL);
00020 return NULL;
00021 }
00022
00023
00024 AsyncFileWriter::AsyncFileWriter() {
00025 pthread_attr_t attr;
00026 struct sched_param param;
00027
00028 pending = 0;
00029
00030
00031
00032 param.sched_priority = sched_get_priority_min(SCHED_OTHER);
00033
00034 pthread_attr_init(&attr);
00035
00036 running = false;
00037 stop = false;
00038
00039 #ifdef FCAM_PLATFORM_OSX
00040
00041 char semName[256];
00042
00043 snprintf(semName, 256, "FCam::AsyncFile::sem::%llx", (long long unsigned)this);
00044 saveQueueSemaphore = sem_open(semName, O_CREAT, 666, 0);
00045 #else
00046 saveQueueSemaphore = new sem_t;
00047 sem_init(saveQueueSemaphore, 0, 0);
00048 #endif
00049 pthread_mutex_init(&saveQueueMutex, NULL);
00050
00051 if ((errno =
00052 -(pthread_attr_setschedparam(&attr, ¶m) ||
00053 pthread_attr_setschedpolicy(&attr, SCHED_OTHER) ||
00054 pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) ||
00055 pthread_create(&thread, &attr, launch_async_file_writer_thread_, this)))) {
00056 error(Event::InternalError, "Error creating async file writer thread");
00057 return;
00058 } else {
00059 running = true;
00060 }
00061 }
00062
00063 AsyncFileWriter::~AsyncFileWriter() {
00064 stop = true;
00065 sem_post(saveQueueSemaphore);
00066 if (running) {
00067 pthread_join(thread, NULL);
00068 }
00069 #ifdef FCAM_PLATFORM_OSX
00070 sem_close(saveQueueSemaphore);
00071 char semName[256];
00072
00073 snprintf(semName, 256, "FCam::AsyncFile::sem::%llx", (long long unsigned)this);
00074 sem_unlink(semName);
00075 #else
00076 sem_destroy(saveQueueSemaphore);
00077 delete saveQueueSemaphore;
00078 #endif
00079
00080 }
00081
00082 void AsyncFileWriter::saveDNG(Frame f, std::string filename) {
00083 pending++;
00084 SaveRequest r;
00085 r.frame = f;
00086 r.filename = filename;
00087 r.fileType = SaveRequest::DNGFrame;
00088 r.quality = 0;
00089
00090 pthread_mutex_lock(&saveQueueMutex);
00091 saveQueue.push(r);
00092 pthread_mutex_unlock(&saveQueueMutex);
00093 sem_post(saveQueueSemaphore);
00094 }
00095
00096 void AsyncFileWriter::saveJPEG(Frame f, std::string filename, int quality) {
00097 pending++;
00098 SaveRequest r;
00099 r.frame = f;
00100 r.filename = filename;
00101 r.quality = quality;
00102 r.fileType = SaveRequest::JPEGFrame;
00103
00104 pthread_mutex_lock(&saveQueueMutex);
00105 saveQueue.push(r);
00106 pthread_mutex_unlock(&saveQueueMutex);
00107 sem_post(saveQueueSemaphore);
00108 }
00109
00110 void AsyncFileWriter::saveJPEG(Image im, std::string filename, int quality) {
00111 pending++;
00112 SaveRequest r;
00113 r.image = im;
00114 r.filename = filename;
00115 r.quality = quality;
00116 r.fileType = SaveRequest::JPEGImage;
00117
00118 pthread_mutex_lock(&saveQueueMutex);
00119 saveQueue.push(r);
00120 pthread_mutex_unlock(&saveQueueMutex);
00121 sem_post(saveQueueSemaphore);
00122 }
00123
00124 void AsyncFileWriter::saveDump(Frame f, std::string filename) {
00125 pending++;
00126 SaveRequest r;
00127 r.frame = f;
00128 r.filename = filename;
00129 r.quality = 0;
00130 r.fileType = SaveRequest::DumpFrame;
00131
00132 pthread_mutex_lock(&saveQueueMutex);
00133 saveQueue.push(r);
00134 pthread_mutex_unlock(&saveQueueMutex);
00135 sem_post(saveQueueSemaphore);
00136 }
00137
00138 void AsyncFileWriter::saveDump(Image im, std::string filename) {
00139 pending++;
00140 SaveRequest r;
00141 r.image = im;
00142 r.filename = filename;
00143 r.quality = 0;
00144 r.fileType = SaveRequest::DumpImage;
00145
00146 pthread_mutex_lock(&saveQueueMutex);
00147 saveQueue.push(r);
00148 pthread_mutex_unlock(&saveQueueMutex);
00149 sem_post(saveQueueSemaphore);
00150 }
00151
00152 void AsyncFileWriter::cancel() {
00153 pthread_mutex_lock(&saveQueueMutex);
00154 while (saveQueue.size()) {
00155 saveQueue.pop();
00156 };
00157 pthread_mutex_unlock(&saveQueueMutex);
00158 }
00159
00160 void AsyncFileWriter::run() {
00161 while (!stop) {
00162 sem_wait(saveQueueSemaphore);
00163 if (stop) return;
00164 SaveRequest r;
00165 pthread_mutex_lock(&saveQueueMutex);
00166 r = saveQueue.front();
00167 saveQueue.pop();
00168 pthread_mutex_unlock(&saveQueueMutex);
00169 switch (r.fileType) {
00170 case SaveRequest::DNGFrame:
00171 FCam::saveDNG(r.frame, r.filename);
00172 break;
00173 case SaveRequest::JPEGFrame:
00174 FCam::saveJPEG(r.frame, r.filename, r.quality);
00175 break;
00176 case SaveRequest::JPEGImage:
00177 FCam::saveJPEG(r.image, r.filename, r.quality);
00178 break;
00179 case SaveRequest::DumpFrame:
00180 FCam::saveDump(r.frame, r.filename);
00181 break;
00182 case SaveRequest::DumpImage:
00183 FCam::saveDump(r.image, r.filename);
00184 break;
00185 default:
00186 cerr << "Corrupted entry in async file writer save queue." << endl;
00187 }
00188
00189 pending--;
00190 }
00191 }
00192 }
00193