- Main Page
- Modules
- Namespaces
- Classes
- Files

- Search for |

- File List
- File Members

# samples/01_video_encode/video_encode_csvparser.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 <iostream>
    00030 #include <cstdlib>
    00031 #include <cstring>
    00032 #include <linux/v4l2-controls.h>
    00033 #include "video_encode.h"
    00034
    00035 #define CHECK_OPTION_VALUE(argp) if(!*argp || (*argp)[0] == '-') \
    00036                                 { \
    00037                                     cerr << "Error: value not specified for option " << arg << endl; \
    00038                                     goto error; \
    00039                                 }
    00040
    00041 #define CSV_PARSE_CHECK_ERROR(condition, str) \
    00042     if (condition) {\
    00043     cerr << "Error: " << str << endl; \
    00044     goto error; \
    00045     }
    00046
    00047 using namespace std;
    00048
    00049 static void
    00050 print_help(void)
    00051 {
    00052     cerr << "\nvideo_encode <in-file> <in-width> <in-height> <encoder-type> <out-file> [OPTIONS]\n\n"
    00053             "Encoder Types:\n"
    00054             "\tH264\n"
    00055             "\tH265\n\n"
    00056             "OPTIONS:\n"
    00057             "\t-h,--help             Prints this text\n"
    00058             "\t--dbg-level <level>   Sets the debug level [Values 0-3]\n\n"
    00059             "\t-br <bitrate>         Bitrate [Default = 4000000]\n"
    00060             "\t-p <profile>          Encoding Profile [Default = baseline]\n"
    00061             "\t-rc <rate-control>    Ratecontrol mode [Default = cbr]\n"
    00062             "\t-ifi <interval>       I-frame Interval [Default = 30]\n"
    00063             "\t-idri <interval>      IDR Interval [Default = 256]\n"
    00064             "\t--insert-spspps-idr   Insert SPS PPS at every IDR [Default = disabled]\n"
    00065             "\t-fps <num> <den>      Encoding fps in num/den [Default = 30/1]\n\n"
    00066             "\t-tt <level>           Temporal Tradeoff level [Default = 0]\n"
    00067             "\t-vbs <size>           Virtual buffer size [Default = 0]\n"
    00068             "\t-nrf <num>            Number of reference frames [Default = 0]\n\n"
    00069             "\t-slt <type>           Slice length type (1 = Number of MBs, 2 = Bytes) [Default = 1]\n"
    00070             "\t-slen <length>        Slice length [Default = 0]\n"
    00071             "\t-sir <interval>       Slice intrarefresh interval [Default = 0]\n\n"
    00072             "\t-nbf <num>            Number of B frames [Default = 0]\n\n"
    00073             "\t-rpc <string>         Change configurable parameters at runtime\n\n"
    00074             "\t--report-metadata     Print encoder output metadata\n"
    00075             "\t--mvdump              Dump encoded motion vectors\n\n"
    00076             "\t-roi <roi_file_path>  Specify roi param file [Default = disabled]\n\n"
    00077             "\t-MinQpI               Specify minimum Qp Value for I frame\n\n"
    00078             "\t-MaxQpI               Specify maximum Qp Value for I frame\n\n"
    00079             "\t-MinQpP               Specify minimum Qp Value for P frame\n\n"
    00080             "\t-MaxQpP               Specify maximum Qp Value for P frame\n\n"
    00081             "\t-MinQpB               Specify minimum Qp Value for B frame\n\n"
    00082             "\t-MaxQpB               Specify maximum Qp Value for B frame\n\n"
    00083             "NOTE: roi parameters need to be feed per frame in following format\n"
    00084             "      <no. of roi regions> <Qpdelta> <left> <top> <width> <height> ...\n"
    00085             "      e.g. [Each line corresponds roi parameters for one frame] \n"
    00086             "      2   -2   34  33  16  19  -3  68  68  16  16\n"
    00087             "      1   -5   40  40  40  40\n"
    00088             "      3   -4   34  34  16  16  -5  70  70  18  18  -3  100  100  34  34\n"
    00089             "Supported Encoding profiles for H.264:\n"
    00090             "\tbaseline\tmain\thigh\n"
    00091             "Supported Encoding profiles for H.265:\n"
    00092             "\tmain\n"
    00093             "Supported Encoding rate control modes:\n"
    00094             "\tcbr\tvbr\n\n"
    00095             "Supported Temporal Tradeoff levels:\n"
    00096             "0:Drop None       1:Drop 1 in 5      2:Drop 1 in 3\n"
    00097             "3:Drop 1 in 2     4:Drop 2 in 3\n\n"
    00098             "Runtime configurable parameter string should be of the form:\n"
    00099             "\"f<frame_num1>,<prop_id1><val>,<prop_id2><val>;f<frame_num1>,<prop_id1><val>,<prop_id2><val>;...\"\n"
    00100             "e.g. \"f20,b8000000,i1;f300,b6000000,r40/1\"\n\n"
    00101             "Property ids:\n"
    00102             "\tb<bitrate>  Bitrate\n"
    00103             "\tr<num/den>  Framerate\n"
    00104             "\ti1          Force I-frame\n\n"
    00105             "NOTE: These encoding parameters are slightly imprecisely updated depending upon the number of\n"
    00106             "frames in queue and/or processed already.\n";
    00107 }
    00108
    00109 static uint32_t
    00110 get_encoder_type(char *arg)
    00111 {
    00112     if (!strcmp(arg, "H264"))
    00113         return V4L2_PIX_FMT_H264;
    00114     if (!strcmp(arg, "H265"))
    00115         return V4L2_PIX_FMT_H265;
    00116     return 0;
    00117 }
    00118
    00119 static int32_t
    00120 get_encoder_ratecontrol(char *arg)
    00121 {
    00122     if (!strcmp(arg, "cbr"))
    00123         return V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
    00124
    00125     if (!strcmp(arg, "vbr"))
    00126         return V4L2_MPEG_VIDEO_BITRATE_MODE_VBR;
    00127
    00128     return -1;
    00129 }
    00130
    00131 static int32_t
    00132 get_encoder_profile_h264(char *arg)
    00133 {
    00134     if (!strcmp(arg, "baseline"))
    00135         return V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
    00136
    00137     if (!strcmp(arg, "main"))
    00138         return V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
    00139
    00140     if (!strcmp(arg, "high"))
    00141         return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
    00142     return -1;
    00143 }
    00144
    00145 static int32_t
    00146 get_encoder_profile_h265(char *arg)
    00147 {
    00148     if (!strcmp(arg, "main"))
    00149         return V4L2_MPEG_VIDEO_H265_PROFILE_MAIN;
    00150
    00151     return -1;
    00152 }
    00153
    00154 static int32_t
    00155 get_encoder_level(char *arg)
    00156 {
    00157     if (!strcmp(arg, "1.0"))
    00158         return V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
    00159
    00160     if (!strcmp(arg, "1b"))
    00161         return V4L2_MPEG_VIDEO_H264_LEVEL_1B;
    00162
    00163     if (!strcmp(arg, "1.1"))
    00164         return V4L2_MPEG_VIDEO_H264_LEVEL_1_1;
    00165
    00166     if (!strcmp(arg, "1.2"))
    00167         return V4L2_MPEG_VIDEO_H264_LEVEL_1_2;
    00168
    00169     if (!strcmp(arg, "1.3"))
    00170         return V4L2_MPEG_VIDEO_H264_LEVEL_1_3;
    00171
    00172     if (!strcmp(arg, "2.0"))
    00173         return V4L2_MPEG_VIDEO_H264_LEVEL_2_0;
    00174
    00175     if (!strcmp(arg, "2.1"))
    00176         return V4L2_MPEG_VIDEO_H264_LEVEL_2_1;
    00177
    00178     if (!strcmp(arg, "2.2"))
    00179         return V4L2_MPEG_VIDEO_H264_LEVEL_2_2;
    00180
    00181     if (!strcmp(arg, "3.0"))
    00182         return V4L2_MPEG_VIDEO_H264_LEVEL_3_0;
    00183
    00184     if (!strcmp(arg, "3.1"))
    00185         return V4L2_MPEG_VIDEO_H264_LEVEL_3_1;
    00186
    00187     if (!strcmp(arg, "3.2"))
    00188         return V4L2_MPEG_VIDEO_H264_LEVEL_3_2;
    00189
    00190     if (!strcmp(arg, "4.0"))
    00191         return V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
    00192
    00193     if (!strcmp(arg, "4.1"))
    00194         return V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
    00195
    00196     if (!strcmp(arg, "4.2"))
    00197         return V4L2_MPEG_VIDEO_H264_LEVEL_4_2;
    00198
    00199     if (!strcmp(arg, "5.0"))
    00200         return V4L2_MPEG_VIDEO_H264_LEVEL_5_0;
    00201
    00202     if (!strcmp(arg, "5.1"))
    00203         return V4L2_MPEG_VIDEO_H264_LEVEL_5_1;
    00204
    00205     return -1;
    00206 }
    00207
    00208 static int32_t
    00209 get_dbg_level(char *arg)
    00210 {
    00211     int32_t log_level = atoi(arg);
    00212
    00213     if (log_level < 0)
    00214     {
    00215         cout << "Warning: invalid log level input, defaulting to setting 0" << endl;
    00216         return 0;
    00217     }
    00218
    00219     if (log_level > 3)
    00220     {
    00221         cout << "Warning: invalid log level input, defaulting to setting 3" << endl;
    00222         return 3;
    00223     }
    00224
    00225     return log_level;
    00226 }
    00227
    00228 int
    00229 parse_csv_args(context_t * ctx, int argc, char *argv[])
    00230 {
    00231     char **argp = argv;
    00232     char *arg = *(++argp);
    00233     int32_t intval;
    00234
    00235     if (argc == 1 || (arg && (!strcmp(arg, "-h") || !strcmp(arg, "--help"))))
    00236     {
    00237         print_help();
    00238         exit(EXIT_SUCCESS);
    00239     }
    00240
    00241     CSV_PARSE_CHECK_ERROR(argc < 6, "Insufficient arguments");
    00242
    00243     ctx->in_file_path = strdup(*argp);
    00244     CSV_PARSE_CHECK_ERROR(!ctx->in_file_path, "Input file not specified");
    00245
    00246     ctx->width = atoi(*(++argp));
    00247     CSV_PARSE_CHECK_ERROR(ctx->width == 0, "Input width should be > 0");
    00248
    00249     ctx->height = atoi(*(++argp));
    00250     CSV_PARSE_CHECK_ERROR(ctx->height == 0, "Input height should be > 0");
    00251
    00252     ctx->encoder_pixfmt = get_encoder_type(*(++argp));
    00253     CSV_PARSE_CHECK_ERROR(ctx->encoder_pixfmt == 0,
    00254                           "Incorrect encoder type");
    00255
    00256     ctx->out_file_path = strdup(*(++argp));
    00257     CSV_PARSE_CHECK_ERROR(!ctx->out_file_path, "Output file not specified");
    00258
    00259     while ((arg = *(++argp)))
    00260     {
    00261         if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
    00262         {
    00263             print_help();
    00264             exit(EXIT_SUCCESS);
    00265         }
    00266         else if (!strcmp(arg, "--dbg-level"))
    00267         {
    00268             argp++;
    00269             CHECK_OPTION_VALUE(argp);
    00270             log_level = get_dbg_level(*argp);
    00271         }
    00272         else if (!strcmp(arg, "-roi"))
    00273         {
    00274             argp++;
    00275             CHECK_OPTION_VALUE(argp);
    00276             ctx->ROI_Param_file_path = strdup(*argp);
    00277         }
    00278         else if (!strcmp(arg, "-fps"))
    00279         {
    00280             argp++;
    00281             CHECK_OPTION_VALUE(argp);
    00282             ctx->fps_n = atoi(*argp);
    00283             argp++;
    00284             CHECK_OPTION_VALUE(argp);
    00285             ctx->fps_d = atoi(*argp);
    00286             CSV_PARSE_CHECK_ERROR(ctx->fps_d == 0, "fps den should be > 0");
    00287         }
    00288         else if (!strcmp(arg, "-br"))
    00289         {
    00290             argp++;
    00291             CHECK_OPTION_VALUE(argp);
    00292             ctx->bitrate = atoi(*argp);
    00293             CSV_PARSE_CHECK_ERROR(ctx->bitrate == 0, "bit rate should be > 0");
    00294         }
    00295         else if (!strcmp(arg, "-ifi"))
    00296         {
    00297             argp++;
    00298             CHECK_OPTION_VALUE(argp);
    00299             ctx->iframe_interval = atoi(*argp);
    00300             CSV_PARSE_CHECK_ERROR(ctx->iframe_interval == 0,
    00301                     "ifi size shoudl be > 0");
    00302         }
    00303         else if (!strcmp(arg, "-idri"))
    00304         {
    00305             argp++;
    00306             CHECK_OPTION_VALUE(argp);
    00307             ctx->idr_interval = atoi(*argp);
    00308             CSV_PARSE_CHECK_ERROR(ctx->idr_interval == 0,
    00309                     "idri size shoudl be > 0");
    00310         }
    00311         else if (!strcmp(arg, "--insert-spspps-idr"))
    00312         {
    00313             ctx->insert_sps_pps_at_idr = true;
    00314         }
    00315         else if (!strcmp(arg, "-l"))
    00316         {
    00317             argp++;
    00318             CHECK_OPTION_VALUE(argp);
    00319             intval = get_encoder_level(*argp);
    00320             CSV_PARSE_CHECK_ERROR(intval == -1,
    00321                     "Unsupported value for level: " << *argp);
    00322             ctx->level = (enum v4l2_mpeg_video_h264_level) intval;
    00323         }
    00324         else if (!strcmp(arg, "-rc"))
    00325         {
    00326             argp++;
    00327             CHECK_OPTION_VALUE(argp);
    00328             intval = get_encoder_ratecontrol(*argp);
    00329             CSV_PARSE_CHECK_ERROR(intval == -1,
    00330                     "Unsupported value for ratecontrol: " << *argp);
    00331             ctx->ratecontrol = (enum v4l2_mpeg_video_bitrate_mode) intval;
    00332         }
    00333         else if (!strcmp(arg, "-rpc"))
    00334         {
    00335             argp++;
    00336             CHECK_OPTION_VALUE(argp);
    00337             ctx->runtime_params_str = new stringstream(*argp);
    00338         }
    00339         else if (!strcmp(arg, "-p"))
    00340         {
    00341             argp++;
    00342             CHECK_OPTION_VALUE(argp);
    00343             if (ctx->encoder_pixfmt == V4L2_PIX_FMT_H264)
    00344             {
    00345                 ctx->profile = get_encoder_profile_h264(*argp);
    00346             }
    00347             else if (ctx->encoder_pixfmt == V4L2_PIX_FMT_H265)
    00348             {
    00349                 ctx->profile = get_encoder_profile_h265(*argp);
    00350             }
    00351             CSV_PARSE_CHECK_ERROR(ctx->profile == (uint32_t) -1,
    00352                         "Unsupported value for profile: " << *argp);
    00353         }
    00354         else if (!strcmp(arg, "-tt"))
    00355         {
    00356             argp++;
    00357             CHECK_OPTION_VALUE(argp);
    00358             ctx->temporal_tradeoff_level =
    00359                 (enum v4l2_enc_temporal_tradeoff_level_type) atoi(*argp);
    00360             CSV_PARSE_CHECK_ERROR(
    00361                     (ctx->temporal_tradeoff_level <
    00362                      V4L2_ENC_TEMPORAL_TRADEOFF_LEVEL_DROPNONE ||
    00363                      ctx->temporal_tradeoff_level >
    00364                      V4L2_ENC_TEMPORAL_TRADEOFF_LEVEL_DROP2IN3),
    00365                     "Unsupported value for temporal tradeoff: " << *argp);
    00366         }
    00367         else if (!strcmp(arg, "-slt"))
    00368         {
    00369             argp++;
    00370             CHECK_OPTION_VALUE(argp);
    00371             switch (atoi(*argp))
    00372             {
    00373                 case 1:
    00374                     ctx->slice_length_type = V4L2_ENC_SLICE_LENGTH_TYPE_MBLK;
    00375                     break;
    00376                 case 2:
    00377                     ctx->slice_length_type = V4L2_ENC_SLICE_LENGTH_TYPE_BITS;
    00378                     break;
    00379                 default:
    00380                     CSV_PARSE_CHECK_ERROR(true,
    00381                             "Unsupported value for slice length type: " << *argp);
    00382             }
    00383         }
    00384         else if (!strcmp(arg, "-slen"))
    00385         {
    00386             argp++;
    00387             CHECK_OPTION_VALUE(argp);
    00388             ctx->slice_length = (uint32_t) atoi(*argp);
    00389             CSV_PARSE_CHECK_ERROR(ctx->slice_length == 0,
    00390                     "Slice length should be > 0");
    00391         }
    00392         else if (!strcmp(arg, "-vbs"))
    00393         {
    00394             argp++;
    00395             CHECK_OPTION_VALUE(argp);
    00396             ctx->virtual_buffer_size = (uint32_t) atoi(*argp);
    00397             CSV_PARSE_CHECK_ERROR(ctx->virtual_buffer_size == 0,
    00398                     "Virtual buffer size should be > 0");
    00399         }
    00400         else if (!strcmp(arg, "-nbf"))
    00401         {
    00402             argp++;
    00403             CHECK_OPTION_VALUE(argp);
    00404             ctx->num_b_frames = (uint32_t) atoi(*argp);
    00405         }
    00406         else if (!strcmp(arg, "-nrf"))
    00407         {
    00408             argp++;
    00409             CHECK_OPTION_VALUE(argp);
    00410             ctx->num_reference_frames = (uint32_t) atoi(*argp);
    00411             CSV_PARSE_CHECK_ERROR(ctx->num_reference_frames == 0,
    00412                     "Num reference frames should be > 0");
    00413         }
    00414         else if (!strcmp(arg, "-sir"))
    00415         {
    00416             argp++;
    00417             CHECK_OPTION_VALUE(argp);
    00418             ctx->slice_intrarefresh_interval = (uint32_t) atoi(*argp);
    00419             CSV_PARSE_CHECK_ERROR(ctx->slice_intrarefresh_interval == 0,
    00420                     "Slice intrarefresh interval should be > 0");
    00421         }
    00422         else if (!strcmp(arg, "-MinQpI"))
    00423         {
    00424             argp++;
    00425             CHECK_OPTION_VALUE(argp);
    00426             ctx->nMinQpI = atoi(*argp);
    00427             CSV_PARSE_CHECK_ERROR(ctx->nMinQpI < 0, "Min Qp should be >= 0");
    00428         }
    00429         else if (!strcmp(arg, "-MaxQpI"))
    00430         {
    00431             argp++;
    00432             CHECK_OPTION_VALUE(argp);
    00433             ctx->nMaxQpI = atoi(*argp);
    00434             CSV_PARSE_CHECK_ERROR(ctx->nMaxQpI > 51, "Max Qp should be <= 51");
    00435         }
    00436         else if (!strcmp(arg, "-MinQpP"))
    00437         {
    00438             argp++;
    00439             CHECK_OPTION_VALUE(argp);
    00440             ctx->nMinQpP = atoi(*argp);
    00441             CSV_PARSE_CHECK_ERROR(ctx->nMinQpP < 0, "Min Qp should be >= 0");
    00442         }
    00443         else if (!strcmp(arg, "-MaxQpP"))
    00444         {
    00445             argp++;
    00446             CHECK_OPTION_VALUE(argp);
    00447             ctx->nMaxQpP = atoi(*argp);
    00448             CSV_PARSE_CHECK_ERROR(ctx->nMaxQpP > 51, "Max Qp should be <= 51");
    00449         }
    00450         else if (!strcmp(arg, "-MinQpB"))
    00451         {
    00452             argp++;
    00453             CHECK_OPTION_VALUE(argp);
    00454             ctx->nMinQpB = atoi(*argp);
    00455             CSV_PARSE_CHECK_ERROR(ctx->nMinQpB < 0, "Min Qp should be >= 0");
    00456         }
    00457         else if (!strcmp(arg, "-MaxQpB"))
    00458         {
    00459             argp++;
    00460             CHECK_OPTION_VALUE(argp);
    00461             ctx->nMaxQpB = atoi(*argp);
    00462             CSV_PARSE_CHECK_ERROR(ctx->nMaxQpB > 51, "Max Qp should be <= 51");
    00463         }
    00464         else if (!strcmp(arg, "--report-metadata"))
    00465         {
    00466             ctx->report_metadata = true;
    00467         }
    00468         else if (!strcmp(arg, "--mvdump"))
    00469         {
    00470             ctx->dump_mv = true;
    00471         }
    00472         else
    00473         {
    00474             CSV_PARSE_CHECK_ERROR(ctx->out_file_path, "Unknown option " << arg);
    00475         }
    00476     }
    00477
    00478     return 0;
    00479
    00480 error:
    00481     print_help();
    00482     return -1;
    00483 }