- Main Page
- Modules
- Namespaces
- Classes
- Files

- Search for |

- File List
- File Members

# samples/07_video_convert/video_convert_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 "video_convert.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->conv0->abort();
    00051     if (ctx->conv1)
    00052     {
    00053         ctx->conv1->abort();
    00054     }
    00055     pthread_cond_broadcast(&ctx->queue_cond);
    00056 }
    00057 static bool
    00058 conv0_capture_dqbuf_thread_callback(struct v4l2_buffer *v4l2_buf,
    00059                                    NvBuffer * buffer, NvBuffer * shared_buffer,
    00060                                    void *arg)
    00061 {
    00062     context_t *ctx = (context_t *) arg;
    00063     NvBuffer *conv1_buffer;
    00064     struct v4l2_buffer conv1_qbuf;
    00065     struct v4l2_plane planes[MAX_PLANES];
    00066
    00067     if (!v4l2_buf)
    00068     {
    00069         cerr << "Failed to dequeue buffer from conv0 capture plane" << endl;
    00070         abort(ctx);
    00071         return false;
    00072     }
    00073
    00074     if (ctx->in_buftype ==  BUF_TYPE_NVBL || ctx->out_buftype == BUF_TYPE_NVBL)
    00075     {
    00076         // Get an empty conv1 output plane buffer from conv1_output_plane_buf_queue
    00077         pthread_mutex_lock(&ctx->queue_lock);
    00078         while (ctx->conv1_output_plane_buf_queue->empty() && !ctx->got_error)
    00079         {
    00080             pthread_cond_wait(&ctx->queue_cond, &ctx->queue_lock);
    00081         }
    00082
    00083         if (ctx->got_error)
    00084         {
    00085             pthread_mutex_unlock(&ctx->queue_lock);
    00086             return false;
    00087         }
    00088         conv1_buffer = ctx->conv1_output_plane_buf_queue->front();
    00089         ctx->conv1_output_plane_buf_queue->pop();
    00090         pthread_mutex_unlock(&ctx->queue_lock);
    00091
    00092         memset(&conv1_qbuf, 0, sizeof(conv1_qbuf));
    00093         memset(&planes, 0, sizeof(planes));
    00094
    00095         conv1_qbuf.index = conv1_buffer->index;
    00096         conv1_qbuf.m.planes = planes;
    00097
    00098         // A reference to buffer is saved which can be used when
    00099         // buffer is dequeued from conv1 output plane
    00100         if (ctx->conv1->output_plane.qBuffer(conv1_qbuf, buffer)  < 0)
    00101         {
    00102             cerr << "Error queueing buffer on conv1 output plane" << endl;
    00103             abort(ctx);
    00104             return false;
    00105         }
    00106
    00107         if (v4l2_buf->m.planes[0].bytesused == 0)
    00108         {
    00109             return false;
    00110         }
    00111     }
    00112     else
    00113     {
    00114         if (v4l2_buf->m.planes[0].bytesused == 0)
    00115         {
    00116             return false;
    00117         }
    00118         write_video_frame(ctx->out_file, *buffer);
    00119         if (ctx->conv0->capture_plane.qBuffer(*v4l2_buf, buffer) < 0)
    00120         {
    00121             cerr << "Error queueing buffer on conv0 capture plane" << endl;
    00122             abort(ctx);
    00123             return false;
    00124         }
    00125     }
    00126     return true;
    00127 }
    00128
    00129 static bool
    00130 conv1_output_dqbuf_thread_callback(struct v4l2_buffer *v4l2_buf,
    00131                                   NvBuffer * buffer, NvBuffer * shared_buffer,
    00132                                   void *arg)
    00133 {
    00134     context_t *ctx = (context_t *) arg;
    00135     struct v4l2_buffer conv0_ret_qbuf;
    00136     struct v4l2_plane planes[MAX_PLANES];
    00137
    00138     if (!v4l2_buf)
    00139     {
    00140         cerr << "Failed to dequeue buffer from conv1 output plane" << endl;
    00141         abort(ctx);
    00142         return false;
    00143     }
    00144
    00145     memset(&conv0_ret_qbuf, 0, sizeof(conv0_ret_qbuf));
    00146     memset(&planes, 0, sizeof(planes));
    00147
    00148     // Get the index of the conv0 capture plane shared buffer
    00149     conv0_ret_qbuf.index = shared_buffer->index;
    00150     conv0_ret_qbuf.m.planes = planes;
    00151
    00152     // Add the dequeued buffer to conv1 empty output buffers queue to
    00153     // conv1_output_plane_buf_queue
    00154     // queue the shared buffer back in conv0 capture plane
    00155     pthread_mutex_lock(&ctx->queue_lock);
    00156     if (ctx->conv0->capture_plane.qBuffer(conv0_ret_qbuf, NULL) < 0)
    00157     {
    00158         cerr << "Error queueing buffer on conv0 capture plane" << endl;
    00159         abort(ctx);
    00160         return false;
    00161     }
    00162     ctx->conv1_output_plane_buf_queue->push(buffer);
    00163     pthread_cond_broadcast(&ctx->queue_cond);
    00164     pthread_mutex_unlock(&ctx->queue_lock);
    00165
    00166     if (v4l2_buf->m.planes[0].bytesused == 0)
    00167     {
    00168         return false;
    00169     }
    00170     return true;
    00171 }
    00172
    00173 static bool
    00174 conv1_capture_dqbuf_thread_callback(struct v4l2_buffer *v4l2_buf,
    00175                                    NvBuffer * buffer, NvBuffer * shared_buffer,
    00176                                    void *arg)
    00177 {
    00178     context_t *ctx = (context_t *) arg;
    00179
    00180     if (!v4l2_buf)
    00181     {
    00182         cerr << "Failed to dequeue buffer from conv1 capture plane" << endl;
    00183         abort(ctx);
    00184         return false;
    00185     }
    00186
    00187     if (v4l2_buf->m.planes[0].bytesused == 0)
    00188     {
    00189         return false;
    00190     }
    00191     write_video_frame(ctx->out_file, *buffer);
    00192     if (ctx->conv1->capture_plane.qBuffer(*v4l2_buf, NULL) < 0)
    00193     {
    00194         cerr << "Error queueing buffer on conv1 capture plane" << endl;
    00195         abort(ctx);
    00196         return false;
    00197     }
    00198     return true;
    00199 }
    00200
    00201 static void
    00202 set_defaults(context_t * ctx)
    00203 {
    00204     memset(ctx, 0, sizeof(context_t));
    00205     ctx->conv1_output_plane_buf_queue = new queue < NvBuffer * >;
    00206     pthread_mutex_init(&ctx->queue_lock, NULL);
    00207     pthread_cond_init(&ctx->queue_cond, NULL);
    00208
    00209     ctx->interpolation_method = (enum v4l2_interpolation_method) -1;
    00210     ctx->tnr_algorithm = (enum v4l2_tnr_algorithm) -1;
    00211     ctx->flip_method = (enum v4l2_flip_method) -1;
    00212 }
    00213
    00214 int
    00215 main(int argc, char *argv[])
    00216 {
    00217     context_t ctx;
    00218     NvVideoConverter *main_conv;
    00219     int ret = 0;
    00220     int error = 0;
    00221     bool eos = false;
    00222
    00223     set_defaults(&ctx);
    00224
    00225     ret = parse_csv_args(&ctx, argc, argv);
    00226     TEST_ERROR(ret < 0, "Error parsing commandline arguments", cleanup);
    00227
    00228     TEST_ERROR(ctx.in_buftype == BUF_TYPE_NVBL &&
    00229             ctx.out_buftype == BUF_TYPE_NVBL,
    00230             "NV BL -> NV BL conversions are not supported", cleanup);
    00231
    00232     ctx.in_file = new ifstream(ctx.in_file_path);
    00233     TEST_ERROR(!ctx.in_file->is_open(), "Could not open input file", cleanup);
    00234
    00235     ctx.out_file = new ofstream(ctx.out_file_path);
    00236     TEST_ERROR(!ctx.out_file->is_open(), "Could not open output file", cleanup);
    00237
    00238     ctx.conv0 = NvVideoConverter::createVideoConverter("conv0");
    00239     TEST_ERROR(!ctx.conv0, "Could not create Video Converter", cleanup);
    00240
    00241     if (ctx.in_buftype == BUF_TYPE_NVBL || ctx.out_buftype == BUF_TYPE_NVBL)
    00242     {
    00243         ctx.conv1 = NvVideoConverter::createVideoConverter("conv1");
    00244         TEST_ERROR(!ctx.conv1, "Could not create Video Converter", cleanup);
    00245     }
    00246
    00247     if (ctx.in_buftype == BUF_TYPE_NVBL)
    00248     {
    00249         main_conv = ctx.conv1;
    00250     }
    00251     else
    00252     {
    00253         main_conv = ctx.conv0;
    00254     }
    00255
    00256     if (ctx.flip_method != -1)
    00257     {
    00258         ret = main_conv->setFlipMethod(ctx.flip_method);
    00259         TEST_ERROR(ret < 0, "Could not set flip method", cleanup);
    00260     }
    00261
    00262     if (ctx.interpolation_method != -1)
    00263     {
    00264         ret = main_conv->setInterpolationMethod(ctx.interpolation_method);
    00265         TEST_ERROR(ret < 0, "Could not set interpolation method", cleanup);
    00266     }
    00267
    00268     if (ctx.tnr_algorithm != -1)
    00269     {
    00270         ret = main_conv->setTnrAlgorithm(ctx.tnr_algorithm);
    00271         TEST_ERROR(ret < 0, "Could not set tnr algorithm", cleanup);
    00272     }
    00273
    00274     if (ctx.crop_rect.width != 0 && ctx.crop_rect.height != 0)
    00275     {
    00276         ret = main_conv->setCropRect(ctx.crop_rect.left, ctx.crop_rect.top,
    00277                 ctx.crop_rect.width, ctx.crop_rect.height);
    00278         TEST_ERROR(ret < 0, "Could not set crop rect for conv0",
    00279                 cleanup);
    00280     }
    00281
    00282     // Set conv0 output plane format
    00283     ret = ctx.conv0->setOutputPlaneFormat(ctx.in_pixfmt, ctx.in_width,
    00284                 ctx.in_height, V4L2_NV_BUFFER_LAYOUT_PITCH);
    00285     TEST_ERROR(ret < 0, "Could not set output plane format for conv0", cleanup);
    00286
    00287     if (ctx.in_buftype == BUF_TYPE_NVBL)
    00288     {
    00289     // Set conv0 capture plane format
    00290     ret = ctx.conv0->setCapturePlaneFormat(ctx.in_pixfmt, ctx.in_width,
    00291                 ctx.in_height, V4L2_NV_BUFFER_LAYOUT_BLOCKLINEAR);
    00292     }
    00293     else if (ctx.out_buftype == BUF_TYPE_NVBL)
    00294     {
    00295     ret = ctx.conv0->setCapturePlaneFormat(ctx.out_pixfmt, ctx.out_width,
    00296                 ctx.out_height, V4L2_NV_BUFFER_LAYOUT_BLOCKLINEAR);
    00297     }
    00298     else
    00299     {
    00300     ret = ctx.conv0->setCapturePlaneFormat(ctx.out_pixfmt, ctx.out_width,
    00301                 ctx.out_height, V4L2_NV_BUFFER_LAYOUT_PITCH);
    00302     }
    00303     TEST_ERROR(ret < 0, "Could not set capture plane format for conv0", cleanup);
    00304
    00305     if (ctx.in_buftype == BUF_TYPE_NVBL)
    00306     {
    00307     // Set conv1 output plane format
    00308     ret =
    00309         ctx.conv1->setOutputPlaneFormat(ctx.in_pixfmt, ctx.in_width,
    00310                                        ctx.in_height, V4L2_NV_BUFFER_LAYOUT_BLOCKLINEAR);
    00311     }
    00312     else if (ctx.out_buftype == BUF_TYPE_NVBL)
    00313     {
    00314     ret =
    00315         ctx.conv1->setOutputPlaneFormat(ctx.out_pixfmt, ctx.out_width,
    00316                                        ctx.out_height, V4L2_NV_BUFFER_LAYOUT_BLOCKLINEAR);
    00317     }
    00318     TEST_ERROR(ret < 0, "Could not set output plane format for conv1", cleanup);
    00319
    00320     if (ctx.conv1)
    00321     {
    00322         // Set conv1 capture plane format
    00323         ret =
    00324             ctx.conv1->setCapturePlaneFormat(ctx.out_pixfmt, ctx.out_width,
    00325                     ctx.out_height, V4L2_NV_BUFFER_LAYOUT_PITCH);
    00326         TEST_ERROR(ret < 0, "Could not set capture plane format for conv1",
    00327                 cleanup);
    00328     }
    00329
    00330     // REQBUF, EXPORT and MAP conv0 output plane buffers
    00331     if (ctx.in_buftype == BUF_TYPE_RAW)
    00332     {
    00333     ret = ctx.conv0->output_plane.setupPlane(V4L2_MEMORY_USERPTR, 10, false, true);
    00334     }
    00335     else
    00336     {
    00337     ret = ctx.conv0->output_plane.setupPlane(V4L2_MEMORY_MMAP, 10, true, false);
    00338     }
    00339     TEST_ERROR(ret < 0, "Error while setting up output plane for conv0",
    00340                cleanup);
    00341
    00342     // REQBUF and EXPORT conv0 capture plane buffers
    00343     // No need to MAP since buffer will be shared to next component
    00344     // and not read in application
    00345     if (ctx.out_buftype == BUF_TYPE_RAW && ctx.in_buftype != BUF_TYPE_NVBL)
    00346     {
    00347     ret =
    00348         ctx.conv0->capture_plane.setupPlane(V4L2_MEMORY_USERPTR, 10, false, true);
    00349     }
    00350     else if (ctx.in_buftype == BUF_TYPE_NVBL || ctx.out_buftype == BUF_TYPE_NVBL)
    00351     {
    00352     ret = ctx.conv0->capture_plane.setupPlane(V4L2_MEMORY_MMAP, 10, false, false);
    00353     }
    00354     else
    00355     {
    00356     ret =
    00357         ctx.conv0->capture_plane.setupPlane(V4L2_MEMORY_MMAP, 10, true, false);
    00358     }
    00359     TEST_ERROR(ret < 0, "Error while setting up capture plane for conv0",
    00360                cleanup);
    00361
    00362     // conv0 output plane STREAMON
    00363     ret = ctx.conv0->output_plane.setStreamStatus(true);
    00364     TEST_ERROR(ret < 0, "Error in output plane streamon for conv0", cleanup);
    00365
    00366     // conv0 capture plane STREAMON
    00367     ret = ctx.conv0->capture_plane.setStreamStatus(true);
    00368     TEST_ERROR(ret < 0, "Error in capture plane streamon for conv0", cleanup);
    00369
    00370     ctx.conv0->
    00371         capture_plane.setDQThreadCallback(conv0_capture_dqbuf_thread_callback);
    00372
    00373     if (ctx.conv1)
    00374     {
    00375         // REQBUF on conv1 output plane buffers
    00376         // DMABUF is used here since it is a shared buffer allocated but another
    00377         // component
    00378         ret = ctx.conv1->output_plane.setupPlane(V4L2_MEMORY_DMABUF, 10, false,
    00379                     false);
    00380         TEST_ERROR(ret < 0, "Error while setting up output plane for conv1",
    00381                 cleanup);
    00382
    00383         // REQBUF on conv1 capture plane buffers,
    00384         // Since USERPTR is used, memory is allocated by the application
    00385         if (ctx.out_buftype == BUF_TYPE_RAW)
    00386         {
    00387             ret = ctx.conv1->capture_plane.setupPlane(V4L2_MEMORY_USERPTR, 10,
    00388                         false, true);
    00389         }
    00390         else
    00391         {
    00392             ret = ctx.conv1->capture_plane.setupPlane(V4L2_MEMORY_MMAP, 10,
    00393                     true, false);
    00394         }
    00395         TEST_ERROR(ret < 0, "Error while setting up capture plane for conv1",
    00396                 cleanup);
    00397
    00398         // conv1 output plane STREAMON
    00399         ret = ctx.conv1->output_plane.setStreamStatus(true);
    00400         TEST_ERROR(ret < 0, "Error in output plane streamon for conv1", cleanup);
    00401
    00402         // conv1 capture plane STREAMON
    00403         ret = ctx.conv1->capture_plane.setStreamStatus(true);
    00404         TEST_ERROR(ret < 0, "Error in capture plane streamon for conv1", cleanup);
    00405
    00406         ctx.conv1->output_plane.setDQThreadCallback(
    00407                 conv1_output_dqbuf_thread_callback);
    00408         ctx.conv1->capture_plane.setDQThreadCallback(
    00409                 conv1_capture_dqbuf_thread_callback);
    00410     }
    00411
    00412     // Start threads to dequeue buffers on conv0 capture plane,
    00413     // conv1 output plane and conv1 capture plane
    00414     ctx.conv0->capture_plane.startDQThread(&ctx);
    00415     if (ctx.conv1)
    00416     {
    00417         ctx.conv1->output_plane.startDQThread(&ctx);
    00418         ctx.conv1->capture_plane.startDQThread(&ctx);
    00419     }
    00420
    00421     // Enqueue all empty conv0 capture plane buffers
    00422     for (uint32_t i = 0; i < ctx.conv0->capture_plane.getNumBuffers(); i++)
    00423     {
    00424         struct v4l2_buffer v4l2_buf;
    00425         struct v4l2_plane planes[MAX_PLANES];
    00426
    00427         memset(&v4l2_buf, 0, sizeof(v4l2_buf));
    00428         memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
    00429
    00430         v4l2_buf.index = i;
    00431         v4l2_buf.m.planes = planes;
    00432
    00433         ret = ctx.conv0->capture_plane.qBuffer(v4l2_buf, NULL);
    00434         if (ret < 0)
    00435         {
    00436             cerr << "Error while queueing buffer at conv0 capture plane" << endl;
    00437             abort(&ctx);
    00438             goto cleanup;
    00439         }
    00440     }
    00441
    00442     if (ctx.conv1)
    00443     {
    00444         // Add all empty conv1 output plane buffers to conv1_output_plane_buf_queue
    00445         for (uint32_t i = 0; i < ctx.conv1->output_plane.getNumBuffers(); i++)
    00446         {
    00447             ctx.conv1_output_plane_buf_queue->push(ctx.conv1->output_plane.
    00448                     getNthBuffer(i));
    00449         }
    00450
    00451         // Enqueue all empty conv1 capture plane buffers
    00452         for (uint32_t i = 0; i < ctx.conv1->capture_plane.getNumBuffers(); i++)
    00453         {
    00454             struct v4l2_buffer v4l2_buf;
    00455             struct v4l2_plane planes[MAX_PLANES];
    00456
    00457             memset(&v4l2_buf, 0, sizeof(v4l2_buf));
    00458             memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
    00459
    00460             v4l2_buf.index = i;
    00461             v4l2_buf.m.planes = planes;
    00462
    00463             ret = ctx.conv1->capture_plane.qBuffer(v4l2_buf, NULL);
    00464             if (ret < 0)
    00465             {
    00466                 cerr << "Error while queueing buffer at conv1 capture plane"
    00467                     << endl;
    00468                 abort(&ctx);
    00469                 goto cleanup;
    00470             }
    00471         }
    00472     }
    00473
    00474     // Read video frame from file and queue buffer on conv0 output plane
    00475     for (uint32_t i = 0; i < ctx.conv0->output_plane.getNumBuffers() &&
    00476             !ctx.got_error && !eos; i++)
    00477     {
    00478         struct v4l2_buffer v4l2_buf;
    00479         struct v4l2_plane planes[MAX_PLANES];
    00480         NvBuffer *buffer = ctx.conv0->output_plane.getNthBuffer(i);
    00481
    00482         memset(&v4l2_buf, 0, sizeof(v4l2_buf));
    00483         memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
    00484
    00485         v4l2_buf.index = i;
    00486         v4l2_buf.m.planes = planes;
    00487
    00488         if (read_video_frame(ctx.in_file, *buffer) < 0)
    00489         {
    00490             cerr << "Could not read complete frame from input file" << endl;
    00491             cerr << "File read complete." << endl;
    00492             v4l2_buf.m.planes[0].bytesused = 0;
    00493             eos = true;
    00494         }
    00495
    00496         ret = ctx.conv0->output_plane.qBuffer(v4l2_buf, NULL);
    00497         if (ret < 0)
    00498         {
    00499             cerr << "Error while queueing buffer at conv0 output plane" << endl;
    00500             abort(&ctx);
    00501             goto cleanup;
    00502         }
    00503     }
    00504
    00505     // Read video frame from file till EOS is reached and queue buffer on conv0 output plane
    00506     while (!ctx.got_error && !ctx.conv0->isInError() &&
    00507             (!ctx.conv1 || !ctx.conv1->isInError()) && !eos)
    00508     {
    00509         struct v4l2_buffer v4l2_buf;
    00510         struct v4l2_plane planes[MAX_PLANES];
    00511         NvBuffer *buffer;
    00512
    00513         memset(&v4l2_buf, 0, sizeof(v4l2_buf));
    00514         memset(planes, 0, sizeof(planes));
    00515
    00516         v4l2_buf.m.planes = planes;
    00517
    00518         if (ctx.conv0->output_plane.dqBuffer(v4l2_buf, &buffer, NULL, 100) < 0)
    00519         {
    00520             cerr << "ERROR while DQing buffer at conv0 output plane" << endl;
    00521             abort(&ctx);
    00522             goto cleanup;
    00523         }
    00524
    00525         if (read_video_frame(ctx.in_file, *buffer) < 0)
    00526         {
    00527             cerr << "Could not read complete frame from input file" << endl;
    00528             cerr << "File read complete." << endl;
    00529             v4l2_buf.m.planes[0].bytesused = 0;
    00530             eos = true;
    00531         }
    00532
    00533         ret = ctx.conv0->output_plane.qBuffer(v4l2_buf, NULL);
    00534         if (ret < 0)
    00535         {
    00536             cerr << "Error while queueing buffer at conv0 output plane" << endl;
    00537             abort(&ctx);
    00538             goto cleanup;
    00539         }
    00540     }
    00541
    00542     if (!ctx.got_error)
    00543     {
    00544         // Wait till all capture plane buffers on conv0 and conv1 are dequeued
    00545         ctx.conv0->waitForIdle(-1);
    00546         if (ctx.conv1)
    00547         {
    00548             ctx.conv1->waitForIdle(-1);
    00549         }
    00550     }
    00551
    00552 cleanup:
    00553     if (ctx.conv0 && ctx.conv0->isInError())
    00554     {
    00555         cerr << "VideoConverter0 is in error" << endl;
    00556         error = 1;
    00557     }
    00558
    00559     if (ctx.conv1 && ctx.conv1->isInError())
    00560     {
    00561         cerr << "VideoConverter1 is in error" << endl;
    00562         error = 1;
    00563     }
    00564
    00565     if (ctx.got_error)
    00566     {
    00567         error = 1;
    00568     }
    00569
    00570     delete ctx.conv1_output_plane_buf_queue;
    00571     delete ctx.in_file;
    00572     delete ctx.out_file;
    00573     // Destructors do all the cleanup, unmapping and deallocating buffers
    00574     // and calling v4l2_close on fd
    00575     delete ctx.conv0;
    00576     delete ctx.conv1;
    00577
    00578     free(ctx.in_file_path);
    00579     free(ctx.out_file_path);
    00580
    00581     if (error)
    00582     {
    00583         cout << "App run failed" << endl;
    00584     }
    00585     else
    00586     {
    00587         cout << "App run was successful" << endl;
    00588     }
    00589     return -error;
    00590 }