- Main Page
- Modules
- Namespaces
- Classes
- Files

- Search for |

- File List
- File Members

# samples/01_video_encode/video_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 <fstream>
    00031 #include <iostream>
    00032 #include <linux/videodev2.h>
    00033 #include <malloc.h>
    00034 #include <sstream>
    00035 #include <string.h>
    00036
    00037 #include "video_encode.h"
    00038
    00039 #define TEST_ERROR(cond, str, label) if(cond) { \
    00040                                         cerr << str << endl; \
    00041                                         error = 1; \
    00042                                         goto label; }
    00043
    00044 #define TEST_PARSE_ERROR(cond, label) if(cond) { \
    00045     cerr << "Error parsing runtime parameter changes string" << endl; \
    00046     goto label; }
    00047
    00048 #define IS_DIGIT(c) (c >= '0' && c <= '9')
    00049
    00050 using namespace std;
    00051
    00052 static void
    00053 abort(context_t *ctx)
    00054 {
    00055     ctx->got_error = true;
    00056     ctx->enc->abort();
    00057 }
    00058
    00059 static int
    00060 write_encoder_output_frame(ofstream * stream, NvBuffer * buffer)
    00061 {
    00062     stream->write((char *) buffer->planes[0].data, buffer->planes[0].bytesused);
    00063     return 0;
    00064 }
    00065
    00066 static bool
    00067 encoder_capture_plane_dq_callback(struct v4l2_buffer *v4l2_buf, NvBuffer * buffer,
    00068                                   NvBuffer * shared_buffer, void *arg)
    00069 {
    00070     context_t *ctx = (context_t *) arg;
    00071     NvVideoEncoder *enc = ctx->enc;
    00072     uint32_t frame_num = ctx->enc->capture_plane.getTotalDequeuedBuffers() - 1;
    00073
    00074     if (v4l2_buf == NULL)
    00075     {
    00076         cout << "Error while dequeing buffer from output plane" << endl;
    00077         abort(ctx);
    00078         return false;
    00079     }
    00080
    00081     // GOT EOS from encoder. Stop dqthread.
    00082     if (buffer->planes[0].bytesused == 0)
    00083     {
    00084         return false;
    00085     }
    00086
    00087     write_encoder_output_frame(ctx->out_file, buffer);
    00088
    00089     if (ctx->report_metadata)
    00090     {
    00091         v4l2_ctrl_videoenc_outputbuf_metadata enc_metadata;
    00092         if (ctx->enc->getMetadata(v4l2_buf->index, enc_metadata) == 0)
    00093         {
    00094             cout << "Frame " << frame_num <<
    00095                 ": isKeyFrame=" << (int) enc_metadata.KeyFrame <<
    00096                 " AvgQP=" << enc_metadata.AvgQP <<
    00097                 " MinQP=" << enc_metadata.FrameMinQP <<
    00098                 " MaxQP=" << enc_metadata.FrameMaxQP <<
    00099                 " EncodedBits=" << enc_metadata.EncodedFrameBits <<
    00100                 endl;
    00101         }
    00102     }
    00103     if (ctx->dump_mv)
    00104     {
    00105         v4l2_ctrl_videoenc_outputbuf_metadata_MV enc_mv_metadata;
    00106         if (ctx->enc->getMotionVectors(v4l2_buf->index, enc_mv_metadata) == 0)
    00107         {
    00108             uint32_t numMVs = enc_mv_metadata.bufSize / sizeof(MVInfo);
    00109             MVInfo *pInfo = enc_mv_metadata.pMVInfo;
    00110
    00111             cout << "Frame " << frame_num << ": Num MVs=" << numMVs << endl;
    00112
    00113             for (uint32_t i = 0; i < numMVs; i++, pInfo++)
    00114             {
    00115                 cout << i << ": mv_x=" << pInfo->mv_x <<
    00116                     " mv_y=" << pInfo->mv_y <<
    00117                     " weight=" << pInfo->weight <<
    00118                     endl;
    00119             }
    00120         }
    00121     }
    00122
    00123     if (enc->capture_plane.qBuffer(*v4l2_buf, NULL) < 0)
    00124     {
    00125         cerr << "Error while Qing buffer at capture plane" << endl;
    00126         abort(ctx);
    00127         return false;
    00128     }
    00129
    00130     return true;
    00131 }
    00132
    00133 static int
    00134 get_next_parsed_pair(context_t *ctx, char *id, uint32_t *value)
    00135 {
    00136     char charval;
    00137
    00138     *ctx->runtime_params_str >> *id;
    00139     if (ctx->runtime_params_str->eof())
    00140     {
    00141         return -1;
    00142     }
    00143
    00144     charval = ctx->runtime_params_str->peek();
    00145     if (!IS_DIGIT(charval))
    00146     {
    00147         return -1;
    00148     }
    00149
    00150     *ctx->runtime_params_str >> *value;
    00151
    00152     *ctx->runtime_params_str >> charval;
    00153     if (ctx->runtime_params_str->eof())
    00154     {
    00155         return 0;
    00156     }
    00157
    00158     return charval;
    00159 }
    00160
    00161 static int
    00162 set_runtime_params(context_t *ctx)
    00163 {
    00164     char charval;
    00165     uint32_t intval;
    00166     int ret;
    00167
    00168     cout << "Frame " << ctx->next_param_change_frame <<
    00169         ": Changing parameters" << endl;
    00170     while (!ctx->runtime_params_str->eof())
    00171     {
    00172         ret = get_next_parsed_pair(ctx, &charval, &intval);
    00173         TEST_PARSE_ERROR(ret < 0, err);
    00174         switch (charval)
    00175         {
    00176             case 'b':
    00177                 ctx->enc->setBitrate(intval);
    00178                 cout << "Bitrate = " << intval << endl;
    00179                 break;
    00180             case 'r':
    00181             {
    00182                 int fps_num = intval;
    00183                 TEST_PARSE_ERROR(ret != '/', err);
    00184
    00185                 ctx->runtime_params_str->seekg(-1, ios::cur);
    00186                 ret = get_next_parsed_pair(ctx, &charval, &intval);
    00187                 TEST_PARSE_ERROR(ret < 0, err);
    00188
    00189                 cout << "Framerate = " << fps_num << "/"  << intval << endl;
    00190
    00191                 ctx->enc->setFrameRate(fps_num, intval);
    00192                 break;
    00193             }
    00194             case 'i':
    00195                 if (intval > 0)
    00196                 {
    00197                     ctx->enc->forceIDR();
    00198                     cout << "Forcing IDR" << endl;
    00199                 }
    00200                 break;
    00201             default:
    00202                 TEST_PARSE_ERROR(true, err);
    00203         }
    00204         switch (ret)
    00205         {
    00206             case 0:
    00207                 delete ctx->runtime_params_str;
    00208                 ctx->runtime_params_str = NULL;
    00209                 return 0;
    00210             case ';':
    00211                 return 0;
    00212             case ',':
    00213                 break;
    00214             default:
    00215                 break;
    00216         }
    00217     }
    00218     return 0;
    00219 err:
    00220     cerr << "Skipping further runtime parameter changes" <<endl;
    00221     delete ctx->runtime_params_str;
    00222     ctx->runtime_params_str = NULL;
    00223     return -1;
    00224 }
    00225
    00226 static int
    00227 get_next_runtime_param_change_frame(context_t *ctx)
    00228 {
    00229     char charval;
    00230     int ret;
    00231
    00232     ret = get_next_parsed_pair(ctx, &charval, &ctx->next_param_change_frame);
    00233     if(ret == 0)
    00234     {
    00235         return 0;
    00236     }
    00237
    00238     TEST_PARSE_ERROR((ret != ';' && ret != ',') || charval != 'f', err);
    00239
    00240     return 0;
    00241
    00242 err:
    00243     cerr << "Skipping further runtime parameter changes" <<endl;
    00244     delete ctx->runtime_params_str;
    00245     ctx->runtime_params_str = NULL;
    00246     return -1;
    00247 }
    00248
    00249 static void
    00250 set_defaults(context_t * ctx)
    00251 {
    00252     memset(ctx, 0, sizeof(context_t));
    00253
    00254     ctx->bitrate = 4 * 1024 * 1024;
    00255     ctx->profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
    00256     ctx->ratecontrol = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
    00257     ctx->iframe_interval = 30;
    00258     ctx->idr_interval = 256;
    00259     ctx->level = V4L2_MPEG_VIDEO_H264_LEVEL_5_1;
    00260     ctx->fps_n = 30;
    00261     ctx->fps_d = 1;
    00262     ctx->num_b_frames = (uint32_t) -1;
    00263     ctx->nMinQpI = (uint32_t)QP_RETAIN_VAL;
    00264     ctx->nMaxQpI = (uint32_t)QP_RETAIN_VAL;
    00265     ctx->nMinQpP = (uint32_t)QP_RETAIN_VAL;
    00266     ctx->nMaxQpP = (uint32_t)QP_RETAIN_VAL;
    00267     ctx->nMinQpB = (uint32_t)QP_RETAIN_VAL;
    00268     ctx->nMaxQpB = (uint32_t)QP_RETAIN_VAL;
    00269 }
    00270
    00271 static void
    00272 populate_roi_Param(std::ifstream * stream, v4l2_enc_frame_ROI_params *VEnc_ROI_params)
    00273 {
    00274     unsigned int ROIIndex = 0;
    00275
    00276     if (!stream->eof()) {
    00277         *stream >> VEnc_ROI_params->num_ROI_regions;
    00278         while (ROIIndex < VEnc_ROI_params->num_ROI_regions)
    00279         {
    00280             *stream >> VEnc_ROI_params->ROI_params[ROIIndex].QPdelta;
    00281             *stream >> VEnc_ROI_params->ROI_params[ROIIndex].ROIRect.left;
    00282             *stream >> VEnc_ROI_params->ROI_params[ROIIndex].ROIRect.top;
    00283             *stream >> VEnc_ROI_params->ROI_params[ROIIndex].ROIRect.width;
    00284             *stream >> VEnc_ROI_params->ROI_params[ROIIndex].ROIRect.height;
    00285             ROIIndex++;
    00286         }
    00287     } else {
    00288         cout << "EOF of ROI_param_file & rewind" << endl;
    00289         stream->clear();
    00290         stream->seekg(0);
    00291     }
    00292 }
    00293
    00294 int
    00295 main(int argc, char *argv[])
    00296 {
    00297     context_t ctx;
    00298     int ret = 0;
    00299     int error = 0;
    00300     bool eos = false;
    00301
    00302     set_defaults(&ctx);
    00303
    00304     ret = parse_csv_args(&ctx, argc, argv);
    00305     TEST_ERROR(ret < 0, "Error parsing commandline arguments", cleanup);
    00306
    00307     if (ctx.runtime_params_str)
    00308     {
    00309         get_next_runtime_param_change_frame(&ctx);
    00310     }
    00311
    00312     if (ctx.encoder_pixfmt == V4L2_PIX_FMT_H265)
    00313     {
    00314         TEST_ERROR(ctx.width < 144 || ctx.height < 144, "Height/Width should be"
    00315             " > 144 for H.265", cleanup);
    00316     }
    00317
    00318     ctx.in_file = new ifstream(ctx.in_file_path);
    00319     TEST_ERROR(!ctx.in_file->is_open(), "Could not open input file", cleanup);
    00320
    00321     ctx.out_file = new ofstream(ctx.out_file_path);
    00322     TEST_ERROR(!ctx.out_file->is_open(), "Could not open output file", cleanup);
    00323
    00324     if (ctx.ROI_Param_file_path) {
    00325         ctx.roi_Param_file = new ifstream(ctx.ROI_Param_file_path);
    00326         TEST_ERROR(!ctx.roi_Param_file->is_open(), "Could not open roi param file", cleanup);
    00327     }
    00328
    00329     ctx.enc = NvVideoEncoder::createVideoEncoder("enc0");
    00330     TEST_ERROR(!ctx.enc, "Could not create encoder", cleanup);
    00331
    00332     // It is necessary that Capture Plane format be set before Output Plane
    00333     // format.
    00334     // Set encoder capture plane format. It is necessary to set width and
    00335     // height on thr capture plane as well
    00336     ret =
    00337         ctx.enc->setCapturePlaneFormat(ctx.encoder_pixfmt, ctx.width,
    00338                                       ctx.height, 2 * 1024 * 1024);
    00339     TEST_ERROR(ret < 0, "Could not set output plane format", cleanup);
    00340
    00341     // Set encoder output plane format
    00342     ret =
    00343         ctx.enc->setOutputPlaneFormat(V4L2_PIX_FMT_YUV420M, ctx.width,
    00344                                       ctx.height);
    00345     TEST_ERROR(ret < 0, "Could not set output plane format", cleanup);
    00346
    00347     ret = ctx.enc->setBitrate(ctx.bitrate);
    00348     TEST_ERROR(ret < 0, "Could not set encoder bitrate", cleanup);
    00349
    00350     ret = ctx.enc->setProfile(ctx.profile);
    00351     TEST_ERROR(ret < 0, "Could not set encoder profile", cleanup);
    00352
    00353     if (ctx.encoder_pixfmt == V4L2_PIX_FMT_H264)
    00354     {
    00355         ret = ctx.enc->setLevel(ctx.level);
    00356         TEST_ERROR(ret < 0, "Could not set encoder level", cleanup);
    00357     }
    00358
    00359     ret = ctx.enc->setRateControlMode(ctx.ratecontrol);
    00360     TEST_ERROR(ret < 0, "Could not set encoder rate control mode", cleanup);
    00361
    00362     ret = ctx.enc->setIDRInterval(ctx.idr_interval);
    00363     TEST_ERROR(ret < 0, "Could not set encoder IDR interval", cleanup);
    00364
    00365     ret = ctx.enc->setIFrameInterval(ctx.iframe_interval);
    00366     TEST_ERROR(ret < 0, "Could not set encoder I-Frame interval", cleanup);
    00367
    00368     ret = ctx.enc->setFrameRate(ctx.fps_n, ctx.fps_d);
    00369     TEST_ERROR(ret < 0, "Could not set framerate", cleanup);
    00370
    00371     if (ctx.temporal_tradeoff_level)
    00372     {
    00373         ret = ctx.enc->setTemporalTradeoff(ctx.temporal_tradeoff_level);
    00374         TEST_ERROR(ret < 0, "Could not set temporal tradeoff level", cleanup);
    00375     }
    00376
    00377     if (ctx.slice_length)
    00378     {
    00379         ret = ctx.enc->setSliceLength(ctx.slice_length_type,
    00380                 ctx.slice_length);
    00381         TEST_ERROR(ret < 0, "Could not set slice length params", cleanup);
    00382     }
    00383
    00384     if (ctx.virtual_buffer_size)
    00385     {
    00386         ret = ctx.enc->setVirtualBufferSize(ctx.virtual_buffer_size);
    00387         TEST_ERROR(ret < 0, "Could not set virtual buffer size", cleanup);
    00388     }
    00389
    00390     if (ctx.num_reference_frames)
    00391     {
    00392         ret = ctx.enc->setNumReferenceFrames(ctx.num_reference_frames);
    00393         TEST_ERROR(ret < 0, "Could not set num reference frames", cleanup);
    00394     }
    00395
    00396     if (ctx.slice_intrarefresh_interval)
    00397     {
    00398         ret = ctx.enc->setSliceIntrarefresh(ctx.slice_intrarefresh_interval);
    00399         TEST_ERROR(ret < 0, "Could not set slice intrarefresh interval", cleanup);
    00400     }
    00401
    00402     if (ctx.insert_sps_pps_at_idr)
    00403     {
    00404         ret = ctx.enc->setInsertSpsPpsAtIdrEnabled(true);
    00405         TEST_ERROR(ret < 0, "Could not set insertSPSPPSAtIDR", cleanup);
    00406     }
    00407
    00408     if (ctx.num_b_frames != (uint32_t) -1)
    00409     {
    00410         ret = ctx.enc->setNumBFrames(ctx.num_b_frames);
    00411         TEST_ERROR(ret < 0, "Could not set number of B Frames", cleanup);
    00412     }
    00413
    00414     if ((ctx.nMinQpI != (uint32_t)QP_RETAIN_VAL) ||
    00415         (ctx.nMaxQpI != (uint32_t)QP_RETAIN_VAL) ||
    00416         (ctx.nMinQpP != (uint32_t)QP_RETAIN_VAL) ||
    00417         (ctx.nMaxQpP != (uint32_t)QP_RETAIN_VAL) ||
    00418         (ctx.nMinQpB != (uint32_t)QP_RETAIN_VAL) ||
    00419         (ctx.nMaxQpB != (uint32_t)QP_RETAIN_VAL))
    00420     {
    00421         ret = ctx.enc->setQpRange(ctx.nMinQpI, ctx.nMaxQpI, ctx.nMinQpP,
    00422                 ctx.nMaxQpP, ctx.nMinQpB, ctx.nMaxQpB);
    00423         TEST_ERROR(ret < 0, "Could not set quantization parameters", cleanup);
    00424     }
    00425
    00426     if (ctx.dump_mv)
    00427     {
    00428         ret = ctx.enc->enableMotionVectorReporting();
    00429         TEST_ERROR(ret < 0, "Could not enable motion vector reporting", cleanup);
    00430     }
    00431
    00432     // Query, Export and Map the output plane buffers so that we can read
    00433     // raw data into the buffers
    00434     ret = ctx.enc->output_plane.setupPlane(V4L2_MEMORY_MMAP, 10, true, false);
    00435     TEST_ERROR(ret < 0, "Could not setup output plane", cleanup);
    00436
    00437     // Query, Export and Map the output plane buffers so that we can write
    00438     // encoded data from the buffers
    00439     ret = ctx.enc->capture_plane.setupPlane(V4L2_MEMORY_MMAP, 10, true, false);
    00440     TEST_ERROR(ret < 0, "Could not setup capture plane", cleanup);
    00441
    00442     // output plane STREAMON
    00443     ret = ctx.enc->output_plane.setStreamStatus(true);
    00444     TEST_ERROR(ret < 0, "Error in output plane streamon", cleanup);
    00445
    00446     // capture plane STREAMON
    00447     ret = ctx.enc->capture_plane.setStreamStatus(true);
    00448     TEST_ERROR(ret < 0, "Error in capture plane streamon", cleanup);
    00449
    00450     ctx.enc->capture_plane.
    00451         setDQThreadCallback(encoder_capture_plane_dq_callback);
    00452
    00453     // startDQThread starts a thread internally which calls the
    00454     // encoder_capture_plane_dq_callback whenever a buffer is dequeued
    00455     // on the plane
    00456     ctx.enc->capture_plane.startDQThread(&ctx);
    00457
    00458     // Enqueue all the empty capture plane buffers
    00459     for (uint32_t i = 0; i < ctx.enc->capture_plane.getNumBuffers(); i++)
    00460     {
    00461         struct v4l2_buffer v4l2_buf;
    00462         struct v4l2_plane planes[MAX_PLANES];
    00463
    00464         memset(&v4l2_buf, 0, sizeof(v4l2_buf));
    00465         memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
    00466
    00467         v4l2_buf.index = i;
    00468         v4l2_buf.m.planes = planes;
    00469
    00470         ret = ctx.enc->capture_plane.qBuffer(v4l2_buf, NULL);
    00471         if (ret < 0)
    00472         {
    00473             cerr << "Error while queueing buffer at capture plane" << endl;
    00474             abort(&ctx);
    00475             goto cleanup;
    00476         }
    00477     }
    00478
    00479     // Read video frame and queue all the output plane buffers
    00480     for (uint32_t i = 0; i < ctx.enc->output_plane.getNumBuffers(); i++)
    00481     {
    00482         struct v4l2_buffer v4l2_buf;
    00483         struct v4l2_plane planes[MAX_PLANES];
    00484         NvBuffer *buffer = ctx.enc->output_plane.getNthBuffer(i);
    00485
    00486         memset(&v4l2_buf, 0, sizeof(v4l2_buf));
    00487         memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
    00488
    00489         v4l2_buf.index = i;
    00490         v4l2_buf.m.planes = planes;
    00491
    00492         if (read_video_frame(ctx.in_file, *buffer) < 0)
    00493         {
    00494             cerr << "Could not read complete frame from input file" << endl;
    00495             v4l2_buf.m.planes[0].bytesused = 0;
    00496         }
    00497
    00498         if (ctx.runtime_params_str &&
    00499             (ctx.enc->output_plane.getTotalQueuedBuffers() ==
    00500                 ctx.next_param_change_frame))
    00501         {
    00502             set_runtime_params(&ctx);
    00503             if (ctx.runtime_params_str)
    00504                 get_next_runtime_param_change_frame(&ctx);
    00505         }
    00506
    00507         if (ctx.ROI_Param_file_path)
    00508         {
    00509             v4l2_enc_frame_ROI_params VEnc_ROI_params;
    00510
    00511             populate_roi_Param(ctx.roi_Param_file, &VEnc_ROI_params);
    00512
    00513             ctx.enc->setROIParams(v4l2_buf.index, VEnc_ROI_params);
    00514             v4l2_buf.reserved2 = v4l2_buf.index;
    00515         }
    00516
    00517         ret = ctx.enc->output_plane.qBuffer(v4l2_buf, NULL);
    00518         if (ret < 0)
    00519         {
    00520             cerr << "Error while queueing buffer at output plane" << endl;
    00521             abort(&ctx);
    00522             goto cleanup;
    00523         }
    00524
    00525         if (v4l2_buf.m.planes[0].bytesused == 0)
    00526         {
    00527             cerr << "File read complete." << endl;
    00528             eos = true;
    00529             break;
    00530         }
    00531     }
    00532
    00533     // Keep reading input till EOS is reached
    00534     while (!ctx.got_error && !ctx.enc->isInError() && !eos)
    00535     {
    00536         struct v4l2_buffer v4l2_buf;
    00537         struct v4l2_plane planes[MAX_PLANES];
    00538         NvBuffer *buffer;
    00539
    00540         memset(&v4l2_buf, 0, sizeof(v4l2_buf));
    00541         memset(planes, 0, sizeof(planes));
    00542
    00543         v4l2_buf.m.planes = planes;
    00544
    00545         if (ctx.enc->output_plane.dqBuffer(v4l2_buf, &buffer, NULL, 10) < 0)
    00546         {
    00547             cerr << "ERROR while DQing buffer at output plane" << endl;
    00548             abort(&ctx);
    00549             goto cleanup;
    00550         }
    00551
    00552         if (ctx.runtime_params_str &&
    00553             (ctx.enc->output_plane.getTotalQueuedBuffers() ==
    00554                 ctx.next_param_change_frame))
    00555         {
    00556             set_runtime_params(&ctx);
    00557             if (ctx.runtime_params_str)
    00558                 get_next_runtime_param_change_frame(&ctx);
    00559         }
    00560         if (read_video_frame(ctx.in_file, *buffer) < 0)
    00561         {
    00562             cerr << "Could not read complete frame from input file" << endl;
    00563             v4l2_buf.m.planes[0].bytesused = 0;
    00564         }
    00565
    00566         if (ctx.ROI_Param_file_path)
    00567         {
    00568             v4l2_enc_frame_ROI_params VEnc_ROI_params;
    00569
    00570             populate_roi_Param(ctx.roi_Param_file, &VEnc_ROI_params);
    00571
    00572             ctx.enc->setROIParams(v4l2_buf.index, VEnc_ROI_params);
    00573             v4l2_buf.reserved2 = v4l2_buf.index;
    00574         }
    00575
    00576         ret = ctx.enc->output_plane.qBuffer(v4l2_buf, NULL);
    00577         if (ret < 0)
    00578         {
    00579             cerr << "Error while queueing buffer at output plane" << endl;
    00580             abort(&ctx);
    00581             goto cleanup;
    00582         }
    00583
    00584         if (v4l2_buf.m.planes[0].bytesused == 0)
    00585         {
    00586             cerr << "File read complete." << endl;
    00587             eos = true;
    00588             break;
    00589         }
    00590     }
    00591
    00592     // Wait till capture plane DQ Thread finishes
    00593     // i.e. all the capture plane buffers are dequeued
    00594     ctx.enc->capture_plane.waitForDQThread(-1);
    00595
    00596 cleanup:
    00597     if (ctx.enc && ctx.enc->isInError())
    00598     {
    00599         cerr << "Encoder is in error" << endl;
    00600         error = 1;
    00601     }
    00602     if (ctx.got_error)
    00603     {
    00604         error = 1;
    00605     }
    00606
    00607     delete ctx.enc;
    00608     delete ctx.in_file;
    00609     delete ctx.out_file;
    00610     delete ctx.roi_Param_file;
    00611
    00612     free(ctx.in_file_path);
    00613     free(ctx.out_file_path);
    00614     free(ctx.ROI_Param_file_path);
    00615     delete ctx.runtime_params_str;
    00616
    00617     if (error)
    00618     {
    00619         cout << "App run failed" << endl;
    00620     }
    00621     else
    00622     {
    00623         cout << "App run was successful" << endl;
    00624     }
    00625     return -error;
    00626 }