00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "NvJpegEncoder.h"
00030 #include "NvLogging.h"
00031 #include <string.h>
00032 #include <malloc.h>
00033
00034 #define MAX(a, b) ((a) > (b) ? (a) : (b))
00035 #define ROUND_UP_4(num) (((num) + 3) & ~3)
00036
00037 #define CAT_NAME "JpegEncoder"
00038
00039 NvJPEGEncoder::NvJPEGEncoder(const char *comp_name)
00040 :NvElement(comp_name, valid_fields)
00041 {
00042 memset(&cinfo, 0, sizeof(cinfo));
00043 memset(&jerr, 0, sizeof(jerr));
00044 cinfo.err = jpeg_std_error(&jerr);
00045
00046 jpeg_create_compress(&cinfo);
00047 jpeg_suppress_tables(&cinfo, TRUE);
00048 }
00049
00050 NvJPEGEncoder *
00051 NvJPEGEncoder::createJPEGEncoder(const char *comp_name)
00052 {
00053 NvJPEGEncoder *jpegenc = new NvJPEGEncoder(comp_name);
00054 if (jpegenc->isInError())
00055 {
00056 delete jpegenc;
00057 return NULL;
00058 }
00059 return jpegenc;
00060 }
00061
00062 NvJPEGEncoder::~NvJPEGEncoder()
00063 {
00064 jpeg_destroy_compress(&cinfo);
00065 CAT_DEBUG_MSG(comp_name << " (" << this << ") destroyed");
00066 }
00067
00068 int
00069 NvJPEGEncoder::encodeFromFd(int fd, J_COLOR_SPACE color_space,
00070 unsigned char **out_buf, unsigned long &out_buf_size)
00071 {
00072 uint32_t buffer_id;
00073
00074 if (fd == -1)
00075 {
00076 COMP_ERROR_MSG("Not encoding because fd = -1");
00077 return -1;
00078 }
00079
00080 buffer_id = profiler.startProcessing();
00081
00082 jpeg_mem_dest(&cinfo, out_buf, &out_buf_size);
00083
00084 cinfo.fd = fd;
00085 cinfo.IsVendorbuf = TRUE;
00086
00087 cinfo.raw_data_in = TRUE;
00088 cinfo.in_color_space = JCS_YCbCr;
00089 jpeg_set_defaults(&cinfo);
00090
00091 switch (color_space)
00092 {
00093 case JCS_YCbCr:
00094 cinfo.in_color_space = JCS_YCbCr;
00095 break;
00096 default:
00097 COMP_ERROR_MSG("Color format " << color_space << " not supported\n");
00098 return -1;
00099 }
00100
00101 jpeg_start_compress (&cinfo, 0);
00102
00103 if (cinfo.err->msg_code)
00104 {
00105 char err_string[256];
00106 cinfo.err->format_message((j_common_ptr) &cinfo, err_string);
00107 COMP_ERROR_MSG ("Error in jpeg_start_compress: " << err_string);
00108 return -1;
00109 }
00110
00111 jpeg_write_raw_data (&cinfo, NULL, 0);
00112 jpeg_finish_compress(&cinfo);
00113
00114 COMP_DEBUG_MSG("Succesfully encoded Buffer fd=" << fd);
00115
00116 profiler.finishProcessing(buffer_id, false);
00117
00118 return 0;
00119 }
00120
00121 int
00122 NvJPEGEncoder::encodeFromBuffer(NvBuffer & buffer, J_COLOR_SPACE color_space,
00123 unsigned char **out_buf, unsigned long &out_buf_size)
00124 {
00125 unsigned char **line[3];
00126
00127 uint32_t comp_height[MAX_CHANNELS];
00128 uint32_t comp_width[MAX_CHANNELS];
00129 uint32_t h_samp[MAX_CHANNELS];
00130 uint32_t v_samp[MAX_CHANNELS];
00131 uint32_t h_max_samp = 0;
00132 uint32_t v_max_samp = 0;
00133 uint32_t channels;
00134
00135 unsigned char *base[MAX_CHANNELS], *end[MAX_CHANNELS];
00136 unsigned int stride[MAX_CHANNELS];
00137
00138 uint32_t width;
00139 uint32_t height;
00140
00141 uint32_t i, j, k;
00142 uint32_t buffer_id;
00143
00144 buffer_id = profiler.startProcessing();
00145
00146 jpeg_mem_dest(&cinfo, out_buf, &out_buf_size);
00147 width = buffer.planes[0].fmt.width;
00148 height = buffer.planes[0].fmt.height;
00149
00150 switch (color_space)
00151 {
00152 case JCS_YCbCr:
00153 channels = 3;
00154
00155 comp_width[0] = width;
00156 comp_height[0] = height;
00157
00158 comp_width[1] = width / 2;
00159 comp_height[1] = height / 2;
00160
00161 comp_width[2] = width / 2;
00162 comp_height[2] = height / 2;
00163
00164 break;
00165 default:
00166 COMP_ERROR_MSG("Color format " << color_space <<
00167 " not supported\n");
00168 return -1;
00169 }
00170
00171 if (channels != buffer.n_planes)
00172 {
00173 COMP_ERROR_MSG("Buffer not in proper format");
00174 return -1;
00175 }
00176
00177 for (i = 0; i < channels; i++)
00178 {
00179 if (comp_width[i] != buffer.planes[i].fmt.width ||
00180 comp_height[i] != buffer.planes[i].fmt.height)
00181 {
00182 COMP_ERROR_MSG("Buffer not in proper format");
00183 return -1;
00184 }
00185 }
00186
00187 h_max_samp = 0;
00188 v_max_samp = 0;
00189
00190 for (i = 0; i < channels; ++i)
00191 {
00192 h_samp[i] = ROUND_UP_4(comp_width[0]) / comp_width[i];
00193 h_max_samp = MAX(h_max_samp, h_samp[i]);
00194 v_samp[i] = ROUND_UP_4(comp_height[0]) / comp_height[i];
00195 v_max_samp = MAX(v_max_samp, v_samp[i]);
00196 }
00197
00198 for (i = 0; i < channels; ++i)
00199 {
00200 h_samp[i] = h_max_samp / h_samp[i];
00201 v_samp[i] = v_max_samp / v_samp[i];
00202 }
00203
00204 cinfo.image_width = width;
00205 cinfo.image_height = height;
00206 cinfo.input_components = channels;
00207 cinfo.in_color_space = color_space;
00208
00209 jpeg_set_defaults(&cinfo);
00210 cinfo.raw_data_in = TRUE;
00211
00212 if (cinfo.in_color_space == JCS_RGB)
00213 jpeg_set_colorspace(&cinfo, JCS_RGB);
00214
00215 switch (color_space)
00216 {
00217 case JCS_YCbCr:
00218 cinfo.in_color_space = JCS_YCbCr;
00219 break;
00220 default:
00221 COMP_ERROR_MSG("Color format " << color_space << " not supported\n");
00222 return -1;
00223 }
00224
00225 for (i = 0; i < channels; i++)
00226 {
00227 cinfo.comp_info[i].h_samp_factor = h_samp[i];
00228 cinfo.comp_info[i].v_samp_factor = v_samp[i];
00229 line[i] = (unsigned char **) malloc(v_max_samp * DCTSIZE *
00230 sizeof(unsigned char *));
00231 }
00232
00233 for (i = 0; i < channels; i++)
00234 {
00235 base[i] = (unsigned char *) buffer.planes[i].data;
00236 stride[i] = buffer.planes[i].fmt.stride;
00237 end[i] = base[i] + comp_height[i] * stride[i];
00238 }
00239
00240 jpeg_start_compress(&cinfo, TRUE);
00241
00242 if (cinfo.err->msg_code)
00243 {
00244 char err_string[256];
00245 cinfo.err->format_message((j_common_ptr) &cinfo, err_string);
00246 COMP_ERROR_MSG ("Error in jpeg_start_compress: " << err_string);
00247 return -1;
00248 }
00249
00250 for (i = 0; i < height; i += v_max_samp * DCTSIZE)
00251 {
00252 for (k = 0; k < channels; k++)
00253 {
00254 for (j = 0; j < v_samp[k] * DCTSIZE; j++)
00255 {
00256 line[k][j] = base[k];
00257 if (base[k] + stride[k] < end[k])
00258 base[k] += stride[k];
00259 }
00260 }
00261 jpeg_write_raw_data(&cinfo, line, v_max_samp * DCTSIZE);
00262 }
00263
00264 jpeg_finish_compress(&cinfo);
00265 for (i = 0; i < channels; i++)
00266 {
00267 free(line[i]);
00268 }
00269 COMP_DEBUG_MSG("Succesfully encoded Buffer");
00270
00271 profiler.finishProcessing(buffer_id, false);
00272
00273 return 0;
00274 }
00275
00276 void
00277 NvJPEGEncoder::setCropRect(uint32_t left, uint32_t top, uint32_t width,
00278 uint32_t height)
00279 {
00280 cinfo.crop_rect.left = left;
00281 cinfo.crop_rect.top = top;
00282 cinfo.crop_rect.width = width;
00283 cinfo.crop_rect.height = height;
00284 }