- Main Page
- Modules
- Namespaces
- Classes
- Files

- Search for |

- File List
- File Members

# samples/05_jpeg_encode/jpeg_encode_main.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 "NvUtils.h"
    00030 #include <errno.h>
    00031 #include <fstream>
    00032 #include <iostream>
    00033 #include <malloc.h>
    00034 #include <string.h>
    00035 #include <unistd.h>
    00036
    00037 #include "jpeg_encode.h"
    00038
    00039 #define TEST_ERROR(cond, str, label) if(cond) { \
    00040                                         cerr << str << endl; \
    00041                                         error = 1; \
    00042                                         goto label; }
    00043
    00044 using namespace std;
    00045
    00046 static void
    00047 abort(context_t * ctx)
    00048 {
    00049     ctx->got_error = true;
    00050     ctx->conv->abort();
    00051 }
    00052
    00053 static bool
    00054 conv_capture_dqbuf_thread_callback(struct v4l2_buffer *v4l2_buf,
    00055                                    NvBuffer * buffer, NvBuffer * shared_buffer,
    00056                                    void *arg)
    00057 {
    00058     context_t *ctx = (context_t *) arg;
    00059     unsigned long out_buf_size = ctx->in_width * ctx->in_height * 3 / 2;
    00060     unsigned char *out_buf = new unsigned char[out_buf_size];
    00061
    00062     if (!v4l2_buf)
    00063     {
    00064         cerr << "Failed to dequeue buffer from conv capture plane" << endl;
    00065         abort(ctx);
    00066         delete[] out_buf;
    00067         return false;
    00068     }
    00069
    00070     if (v4l2_buf->m.planes[0].bytesused > 0)
    00071     {
    00072         if (ctx->jpegenc->encodeFromFd(buffer->planes[0].fd, JCS_YCbCr, &out_buf,
    00073                 out_buf_size) < 0)
    00074         {
    00075             cerr << "Error while encoding from fd" << endl;
    00076             ctx->got_error = true;
    00077         }
    00078         else
    00079         {
    00080             ctx->out_file->write((char *) out_buf, out_buf_size);
    00081         }
    00082     }
    00083
    00084     delete[] out_buf;
    00085
    00086     return false;
    00087 }
    00088
    00089 static void
    00090 set_defaults(context_t * ctx)
    00091 {
    00092     memset(ctx, 0, sizeof(context_t));
    00093     ctx->use_fd = true;
    00094     ctx->in_pixfmt = V4L2_PIX_FMT_YUV420M;
    00095 }
    00096
    00097 int
    00098 main(int argc, char *argv[])
    00099 {
    00100     context_t ctx;
    00101     int ret = 0;
    00102     int error = 0;
    00103
    00104     set_defaults(&ctx);
    00105
    00106     ret = parse_csv_args(&ctx, argc, argv);
    00107     TEST_ERROR(ret < 0, "Error parsing commandline arguments", cleanup);
    00108
    00109     ctx.in_file = new ifstream(ctx.in_file_path);
    00110     TEST_ERROR(!ctx.in_file->is_open(), "Could not open input file", cleanup);
    00111
    00112     ctx.out_file = new ofstream(ctx.out_file_path);
    00113     TEST_ERROR(!ctx.out_file->is_open(), "Could not open output file", cleanup);
    00114
    00115     ctx.jpegenc = NvJPEGEncoder::createJPEGEncoder("jpenenc");
    00116     TEST_ERROR(!ctx.jpegenc, "Could not create Jpeg Encoder", cleanup);
    00117
    00118     ctx.jpegenc->setCropRect(ctx.crop_left, ctx.crop_top,
    00119             ctx.crop_width, ctx.crop_height);
    00120
    00121     if (!ctx.use_fd)
    00122     {
    00123         unsigned long out_buf_size = ctx.in_width * ctx.in_height * 3 / 2;
    00124         unsigned char *out_buf = new unsigned char[out_buf_size];
    00125
    00126         NvBuffer buffer(V4L2_PIX_FMT_YUV420M, ctx.in_width,
    00127                 ctx.in_height, 0);
    00128
    00129         buffer.allocateMemory();
    00130
    00131         ret = read_video_frame(ctx.in_file, buffer);
    00132         TEST_ERROR(ret < 0, "Could not read a complete frame from file",
    00133                 cleanup);
    00134
    00135         ret = ctx.jpegenc->encodeFromBuffer(buffer, JCS_YCbCr, &out_buf,
    00136                 out_buf_size);
    00137         TEST_ERROR(ret < 0, "Error while encoding from buffer", cleanup);
    00138
    00139         ctx.out_file->write((char *) out_buf, out_buf_size);
    00140         delete[] out_buf;
    00141
    00142         goto cleanup;
    00143     }
    00144
    00145     ctx.conv = NvVideoConverter::createVideoConverter("conv");
    00146     TEST_ERROR(!ctx.conv, "Could not create Video Converter", cleanup);
    00147
    00148     // Set conv output plane format
    00149     ret =
    00150         ctx.conv->setOutputPlaneFormat(V4L2_PIX_FMT_YUV420M, ctx.in_width,
    00151                                        ctx.in_height,
    00152                                        V4L2_NV_BUFFER_LAYOUT_PITCH);
    00153     TEST_ERROR(ret < 0, "Could not set output plane format for conv", cleanup);
    00154
    00155     // Set conv capture plane format
    00156     ret =
    00157         ctx.conv->setCapturePlaneFormat(ctx.in_pixfmt, ctx.in_width,
    00158                                         ctx.in_height,
    00159                                         V4L2_NV_BUFFER_LAYOUT_BLOCKLINEAR);
    00160     TEST_ERROR(ret < 0, "Could not set capture plane format for conv", cleanup);
    00161
    00162     // REQBUF, EXPORT and MAP conv output plane buffers
    00163     ret = ctx.conv->output_plane.setupPlane(V4L2_MEMORY_MMAP, 1, true, false);
    00164     TEST_ERROR(ret < 0, "Error while setting up output plane for conv",
    00165                cleanup);
    00166
    00167     // REQBUF and EXPORT conv capture plane buffers
    00168     // No need to MAP since buffer will be shared to next component
    00169     // and not read in application
    00170     ret =
    00171         ctx.conv->capture_plane.setupPlane(V4L2_MEMORY_MMAP, 1,
    00172                                             !ctx.use_fd, false);
    00173     TEST_ERROR(ret < 0, "Error while setting up capture plane for conv",
    00174                cleanup);
    00175
    00176     // conv output plane STREAMON
    00177     ret = ctx.conv->output_plane.setStreamStatus(true);
    00178     TEST_ERROR(ret < 0, "Error in output plane streamon for conv", cleanup);
    00179
    00180     // conv capture plane STREAMON
    00181     ret = ctx.conv->capture_plane.setStreamStatus(true);
    00182     TEST_ERROR(ret < 0, "Error in capture plane streamon for conv", cleanup);
    00183
    00184     ctx.conv->
    00185         capture_plane.setDQThreadCallback(conv_capture_dqbuf_thread_callback);
    00186
    00187     // Start threads to dequeue buffers on conv capture plane
    00188     ctx.conv->capture_plane.startDQThread(&ctx);
    00189
    00190     // Enqueue all empty conv capture plane buffers
    00191     for (uint32_t i = 0; i < ctx.conv->capture_plane.getNumBuffers(); i++)
    00192     {
    00193         struct v4l2_buffer v4l2_buf;
    00194         struct v4l2_plane planes[MAX_PLANES];
    00195
    00196         memset(&v4l2_buf, 0, sizeof(v4l2_buf));
    00197         memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
    00198
    00199         v4l2_buf.index = i;
    00200         v4l2_buf.m.planes = planes;
    00201
    00202         ret = ctx.conv->capture_plane.qBuffer(v4l2_buf, NULL);
    00203         if (ret < 0)
    00204         {
    00205             cerr << "Error while queueing buffer at conv capture plane" << endl;
    00206             abort(&ctx);
    00207             goto cleanup;
    00208         }
    00209     }
    00210
    00211     {
    00212         struct v4l2_buffer v4l2_buf;
    00213         struct v4l2_plane planes[MAX_PLANES];
    00214         NvBuffer *buffer = ctx.conv->output_plane.getNthBuffer(0);
    00215
    00216         memset(&v4l2_buf, 0, sizeof(v4l2_buf));
    00217         memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
    00218
    00219         v4l2_buf.index = 0;
    00220         v4l2_buf.m.planes = planes;
    00221
    00222         if (read_video_frame(ctx.in_file, *buffer) < 0)
    00223         {
    00224             cerr << "Could not read a complete frame from file" << endl;
    00225             v4l2_buf.m.planes[0].bytesused = 0;
    00226         }
    00227
    00228         ret = ctx.conv->output_plane.qBuffer(v4l2_buf, NULL);
    00229         if (ret < 0)
    00230         {
    00231             cerr << "Error while queueing buffer at conv output plane" << endl;
    00232             abort(&ctx);
    00233             goto cleanup;
    00234         }
    00235     }
    00236
    00237     // Wait till all capture plane buffers on conv are dequeued
    00238     ctx.conv->capture_plane.waitForDQThread(2000);
    00239
    00240 cleanup:
    00241     if (ctx.conv && ctx.conv->isInError())
    00242     {
    00243         cerr << "VideoConverter is in error" << endl;
    00244         error = 1;
    00245     }
    00246
    00247     if (ctx.got_error)
    00248     {
    00249         error = 1;
    00250     }
    00251
    00252     delete ctx.in_file;
    00253     delete ctx.out_file;
    00254     // Destructors do all the cleanup, unmapping and deallocating buffers
    00255     // and calling v4l2_close on fd
    00256     delete ctx.conv;
    00257     delete ctx.jpegenc;
    00258
    00259     free(ctx.in_file_path);
    00260     free(ctx.out_file_path);
    00261
    00262     if (error)
    00263     {
    00264         cout << "App run failed" << endl;
    00265     }
    00266     else
    00267     {
    00268         cout << "App run was successful" << endl;
    00269     }
    00270     return -error;
    00271 }