- Main Page
- Modules
- Namespaces
- Classes
- Files

- Search for |

- File List
- File Members

# samples/common/classes/NvJpegEncoder.cpp

Go to the documentation of this file.

    00001 /*
    00002  * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
    00003  *
    00004  * Redistribution and use in source and binary forms, with or without
    00005  * modification, are permitted provided that the following conditions
    00006  * are met:
    00007  *  * Redistributions of source code must retain the above copyright
    00008  *    notice, this list of conditions and the following disclaimer.
    00009  *  * Redistributions in binary form must reproduce the above copyright
    00010  *    notice, this list of conditions and the following disclaimer in the
    00011  *    documentation and/or other materials provided with the distribution.
    00012  *  * Neither the name of NVIDIA CORPORATION nor the names of its
    00013  *    contributors may be used to endorse or promote products derived
    00014  *    from this software without specific prior written permission.
    00015  *
    00016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
    00017  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    00018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    00019  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    00020  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    00021  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    00022  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    00023  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
    00024  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    00026  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    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 }