From 00d0905bb34476729b8588679776515c77407694 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 20 May 2013 10:20:33 +0200 Subject: Added codec parameters setting in command line Signed-off-by: Andrzej Hajda --- v4l2-mfc-encoder/args.c | 116 +++++++++++++++++++++++++++++++++++++++++++----- v4l2-mfc-encoder/args.h | 5 ++- v4l2-mfc-encoder/main.c | 6 +-- 3 files changed, 110 insertions(+), 17 deletions(-) diff --git a/v4l2-mfc-encoder/args.c b/v4l2-mfc-encoder/args.c index 98ef886..282b3cb 100644 --- a/v4l2-mfc-encoder/args.c +++ b/v4l2-mfc-encoder/args.c @@ -30,20 +30,87 @@ #include "common.h" #include "args.h" +struct { + int id; + char *name; +} ctrls[] = { + { V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE, "force_frame"}, + { V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE, "frame_skip_mode"}, + { V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY, "h264_arc_activity"}, + { V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK, "h264_arc_dark"}, + { V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH, "h264_arc_smooth"}, + { V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC, "h264_arc_static"}, + { V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P, "h264_ref_pic"}, + { V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV, "padding_yuv"}, + { V4L2_CID_MPEG_MFC51_VIDEO_PADDING, "padding"}, + { V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT, "rc_fixed_target_bit"}, + { V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF, "rc_react_coeff"}, + { V4L2_CID_MPEG_VIDEO_B_FRAMES, "b_frames"}, + { V4L2_CID_MPEG_VIDEO_BITRATE, "bitrate"}, + { V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB, "intra_refresh_mb"}, + { V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE, "rc_enable"}, + { V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, "gop_closure"}, + { V4L2_CID_MPEG_VIDEO_GOP_SIZE, "gop_size"}, + { V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP, "h263_b_qp"}, + { V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP, "h263_i_qp"}, + { V4L2_CID_MPEG_VIDEO_H263_MAX_QP, "h263_max_qp"}, + { V4L2_CID_MPEG_VIDEO_H263_MIN_QP, "h263_min_qp"}, + { V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP, "h263_p_qp"}, + { V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM, "h264_8x8_transform"}, + { V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP, "h264_b_qp"}, + { V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE, "h264_cpb_size"}, + { V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE, "h264_entropy"}, + { V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, "h264_i_qp"}, + { V4L2_CID_MPEG_VIDEO_H264_I_PERIOD, "h264_i_period"}, + { V4L2_CID_MPEG_VIDEO_H264_LEVEL, "h264_level"}, + { V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA, "h264_loop_filter_alpha"}, + { V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, "h264_loop_filter_beta"}, + { V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE, "h264_loop_filter_mode"}, + { V4L2_CID_MPEG_VIDEO_H264_MAX_QP, "h264_max_qp"}, + { V4L2_CID_MPEG_VIDEO_H264_MIN_QP, "h264_min_qp"}, + { V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, "h264_p_qp"}, + { V4L2_CID_MPEG_VIDEO_H264_PROFILE, "h264_profile"}, + { V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT, "h264_vui_sar_height"}, + { V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH, "h264_vui_sar_width"}, + { V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE, "h264_vui_sar"}, + { V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC, "h264_vui_sar_idc"}, + { V4L2_CID_MPEG_VIDEO_HEADER_MODE, "header_mode"}, + { V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE, "mb_rc"}, + { V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP, "mpeg4_b_qp"}, + { V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP, "mpeg4_i_qp"}, + { V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL, "mpeg4_level"}, + { V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP, "mpeg4_max_qp"}, + { V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP, "mpeg4_min_qp"}, + { V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP, "mpeg4_p_qp"}, + { V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE, "mpeg4_profile"}, + { V4L2_CID_MPEG_VIDEO_MPEG4_QPEL, "mpeg4_qpel"}, + { V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES, "slice_max_bytes"}, + { V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB, "slice_max_mb"}, + { V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE, "slice_mode"}, + { V4L2_CID_MPEG_VIDEO_VBV_SIZE, "vbv_size"}, +}; + void print_usage(char const *name) { + int i; printf("Usage: %s [args]\n" "\t-i - FIMC camera device (e.g. /dev/video1)\n" "\t If not specified demo input device is used\n" "\t-m - (required) MFC device (e.g. /dev/video8)\n" "\t-o - Output file name\n" - "\t-c - The codec of the encoded stream\n" + "\t-c [,param[=val]]...\n" + "\t - The codec of the encoded stream optionally\n" + "\t followed by comma separated parameters.\n" "\t Available codecs: mpeg4, h263, h264\n" "\t-d - Number of frames to encode\n" "\t-r - Frame rate\n" - "\t-b - Bitrate\n" "\t-s - Size of frame in format WxH\n" + "Codec parameters:\n" , name); + + for (i = 0; i < array_len(ctrls); ++i) { + printf("\t%s\n", ctrls[i].name); + } } int get_codec(char *str) @@ -67,15 +134,26 @@ void set_options_default(struct options *o) o->rate = 25; o->out_name = "demo.out"; o->codec = V4L2_PIX_FMT_H264; - o->bitrate = 1000; } int parse_args(struct options *opts, int argc, char **argv) { - int c; + static const int codecs[] = { + V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_H263, V4L2_PIX_FMT_H264 }; + const int nctrls = array_len(ctrls); + char *tokens[nctrls + 4]; + char *s, *v; + int c, i; set_options_default(opts); + for (i = 0; i < nctrls; ++i) + tokens[i] = ctrls[i].name; + tokens[i++] = "mpeg4"; + tokens[i++] = "h263"; + tokens[i++] = "h264"; + tokens[i++] = NULL; + while ((c = getopt(argc, argv, "i:m:o:c:d:r:s:b:")) != -1) { switch (c) { case 'i': @@ -88,11 +166,28 @@ int parse_args(struct options *opts, int argc, char **argv) opts->out_name = optarg; break; case 'c': - opts->codec = get_codec(optarg); - if (opts->codec == 0) { - err("Unknown codec"); - return -1; - } + s = optarg; + + while (*s) { + c = getsubopt(&s, tokens, &v); + if (c < 0) { + err("unknown codec option '%s'", v); + return -1; + } else if (c < nctrls) { + int *ctl = opts->ctrls[opts->nctrls++]; + if (opts->nctrls > MAX_CTRLS) { + err("Too many codec options"); + return -1; + } + ctl[0] = ctrls[c].id; + ctl[1] = v ? atoi(v) : 1; + dbg("opt %s=%d", ctrls[c].name, ctl[1]); + } else { + dbg("codec: %.04s", + (char *)&codecs[c - nctrls]); + opts->codec = codecs[c - nctrls]; + } + }; break; case 'd': opts->duration = atoi(optarg); @@ -109,9 +204,6 @@ int parse_args(struct options *opts, int argc, char **argv) } opts->height = atoi(++sep); break; - case 'b': - opts->bitrate = atoi(optarg); - break; } default: return -1; diff --git a/v4l2-mfc-encoder/args.h b/v4l2-mfc-encoder/args.h index 757cb2f..f63b99e 100644 --- a/v4l2-mfc-encoder/args.h +++ b/v4l2-mfc-encoder/args.h @@ -25,6 +25,8 @@ #include "common.h" +#define MAX_CTRLS 100 + struct options { char *in_name; char *mfc_name; @@ -34,7 +36,8 @@ struct options { int height; int duration; int rate; - int bitrate; + int nctrls; + int ctrls[MAX_CTRLS][2]; }; void print_usage(char const *name); diff --git a/v4l2-mfc-encoder/main.c b/v4l2-mfc-encoder/main.c index 5681bab..22bca26 100644 --- a/v4l2-mfc-encoder/main.c +++ b/v4l2-mfc-encoder/main.c @@ -76,10 +76,8 @@ int main(int argc, char *argv[]) if (mfc_set_rate(mfc, opts.rate)) return 1; - if (mfc_set_bitrate(mfc, opts.bitrate)) - return 1; - - mfc_set_mpeg_control(mfc, V4L2_CID_MPEG_VIDEO_B_FRAMES, 2); + for (i = 0; i < opts.nctrls; ++i) + mfc_set_mpeg_control(mfc, opts.ctrls[i][0], opts.ctrls[i][1]); if (opts.in_name) if (v4l_copy_fmt(mfc, DIR_IN, input, DIR_OUT)) -- cgit v1.2.3