diff --git a/drm.c b/drm.c index 27953a2..59583a3 100644 --- a/drm.c +++ b/drm.c @@ -649,7 +649,8 @@ int display_engine_start(int drm_fd, unsigned int width, unsigned int height, struct format_description *format, struct video_buffer *video_buffers, unsigned int count, struct gem_buffer **buffers, - struct display_setup *setup) + struct display_setup *setup, + bool quiet) { struct video_buffer *video_buffer; struct gem_buffer *buffer; @@ -824,7 +825,8 @@ int display_engine_start(int drm_fd, unsigned int width, unsigned int height, } int display_engine_stop(int drm_fd, struct gem_buffer *buffers, - struct display_setup *setup) + struct display_setup *setup, + bool quiet) { struct gem_buffer *buffer; unsigned int i; @@ -862,7 +864,8 @@ int display_engine_stop(int drm_fd, struct gem_buffer *buffers, int display_engine_show(int drm_fd, unsigned int index, struct video_buffer *video_buffers, - struct gem_buffer *buffers, struct display_setup *setup) + struct gem_buffer *buffers, struct display_setup *setup, + bool quiet) { struct video_buffer *video_buffer; struct gem_buffer *buffer; diff --git a/presets.c b/presets.c index 098f97a..bba2432 100644 --- a/presets.c +++ b/presets.c @@ -23,8 +23,8 @@ #include #include #include -#include -#include +//#include +//#include #include "v4l2-request-test.h" diff --git a/v4l2-request-test.c b/v4l2-request-test.c index 2531e7c..8a7e7ce 100644 --- a/v4l2-request-test.c +++ b/v4l2-request-test.c @@ -37,6 +37,24 @@ #include "v4l2-request-test.h" +const struct codec codec[] = { + { + .name = "MPEG-2", + .description = "Moving Pictures Expert Group Version-4 (MPEG-2)", + .type = CODEC_TYPE_MPEG2, + }, + { + .name = "H.264", + .description = "Moving Pictures Expert Group Version-4 (MPEG-4)", + .type = CODEC_TYPE_H264, + }, + { + .name = "H.265", + .description = "High-Efficiency Video Coding (HEVC)", + .type = CODEC_TYPE_H265, + }, +}; + struct format_description formats[] = { { .description = "NV12 YUV", @@ -64,20 +82,22 @@ struct format_description formats[] = { static void print_help(void) { - printf("Usage: v4l2-request-test [OPTIONS] [SLICES PATH]\n\n" - "Options:\n" - " -v [video path] path for the video node\n" - " -m [media path] path for the media node\n" - " -d [DRM path] path for the DRM node\n" - " -D [DRM driver] DRM driver to use\n" - " -s [slices filename format] format for filenames in the slices path\n" - " -f [fps] number of frames to display per second\n" - " -P [video preset] video preset to use\n" - " -i enable interactive mode\n" - " -l loop preset frames\n" - " -q enable quiet mode\n" - " -h help\n\n" - "Video presets:\n"); + printf("Usage: v4l2-request-test [OPTIONS]\n\n" + "Options:\n" + " -v, --device \n" + " --video-device Use device as the video device.\n" + " -m, --media-device Use device as the media device.\n" + " -d, --drm-device Use device as DRM device.\n" + " -D, --drm-driver Use given DRM driver.\n" + " -s, --slices-path Use to find stored video slices.\n" + " -S, --slices-format \n" + " Regex/format describing filenames stored in the slices path.\n" + " -f, --fps Display given number of frames per seconds.\n" + " -P, --preset-name Use given preset-name for video decoding.\n" + " -i, --interactive Enable interactive mode.\n" + " -l, --loop Loop preset frames.\n" + " -q, --quiet Enable quiet mode.\n" + " -h, --help This help message.\n\n"); presets_usage(); } @@ -85,37 +105,34 @@ static void print_help(void) static void print_summary(struct config *config, struct preset *preset) { printf("Config:\n"); - printf(" Video path: %s\n", config->video_path); - printf(" Media path: %s\n", config->media_path); - printf(" DRM path: %s\n", config->drm_path); - printf(" DRM driver: %s\n", config->drm_driver); - printf(" Slices path: %s\n", config->slices_path); - printf(" Slices filename format: %s\n", config->slices_filename_format); - printf(" FPS: %d\n\n", config->fps); + printf(" Video device: %s\n", config->video_path); + printf(" Media device: %s\n", config->media_path); + printf(" DRM device: %s\n", config->drm_path); + printf(" DRM driver: %s\n", config->drm_driver); + printf(" Slices path: %s\n", config->slices_path); + printf(" Slices format: %s\n", config->slices_filename_format); + printf(" FPS: %d\n\n", config->fps); printf("Preset:\n"); - printf(" Name: %s\n", preset->name); - printf(" Description: %s\n", preset->description); - printf(" License: %s\n", preset->license); - printf(" Attribution: %s\n", preset->attribution); - printf(" Width: %d\n", preset->width); - printf(" Height: %d\n", preset->height); + printf(" Name: %s\n", preset->name); + printf(" Description: %s\n", preset->description); + printf(" License: %s\n", preset->license); + printf(" Attribution: %s\n", preset->attribution); + printf(" Width: %d\n", preset->width); + printf(" Height: %d\n", preset->height); printf(" Frames count: %d\n", preset->frames_count); - printf(" Format: "); + printf(" Codec Type: "); switch (preset->type) { case CODEC_TYPE_MPEG2: - printf("MPEG2"); - break; case CODEC_TYPE_H264: - printf("H264"); - break; case CODEC_TYPE_H265: - printf("H265"); + printf("%s -> %s", + codec[preset->type].name, codec[preset->type].description); break; default: - printf("Invalid"); + printf("Invalid codec type!"); break; } @@ -257,7 +274,26 @@ int main(int argc, char *argv[]) setup_config(&config); while (1) { - opt = getopt(argc, argv, "v:m:d:D:s:f:P:ilqh"); + int option_index = 0; + static struct option long_options[] = { + { "device", required_argument, 0, 'v' }, + { "video-device", required_argument, 0, 'v' }, + { "media-device", required_argument, 0, 'm' }, + { "drm-device", required_argument, 0, 'd' }, + { "drm-driver", required_argument, 0, 'D' }, + { "slices-path", required_argument, 0, 's'}, + { "slices-format", required_argument, 0, 'S'}, + { "fps", required_argument, 0, 'f' }, + { "preset-name", required_argument, 0, 'P'}, + { "interactive", no_argument, 0, 'i'}, + { "loop", no_argument, 0, 'l'}, + { "quiet", no_argument, 0, 'q'}, + { "help", no_argument, 0, 'h'}, + { 0, 0, 0, 0 } + }; + + opt = getopt_long(argc, argv, "v:m:d:D:s:S:f:P:ilqh", + long_options, &option_index); if (opt == -1) break; @@ -279,6 +315,10 @@ int main(int argc, char *argv[]) config.drm_driver = strdup(optarg); break; case 's': + free(config.slices_path); + config.slices_path = strdup(optarg); + break; + case 'S': free(config.slices_filename_format); config.slices_filename_format = strdup(optarg); break; @@ -320,9 +360,7 @@ int main(int argc, char *argv[]) width = preset->width; height = preset->height; - if (optind < argc) - config.slices_path = strdup(argv[optind]); - else + if (config.slices_path == NULL) asprintf(&config.slices_path, "data/%s", config.preset_name); print_summary(&config, preset); @@ -360,7 +398,8 @@ int main(int argc, char *argv[]) for (i = 0; i < ARRAY_SIZE(formats); i++) { test = video_engine_format_test(video_fd, formats[i].v4l2_mplane, width, - height, formats[i].v4l2_format); + height, formats[i].v4l2_format, + config.quiet); if (test) { selected_format = &formats[i]; break; @@ -375,7 +414,8 @@ int main(int argc, char *argv[]) printf("Destination format: %s\n", selected_format->description); - test = video_engine_capabilities_test(video_fd, V4L2_CAP_STREAMING); + test = video_engine_capabilities_test(video_fd, V4L2_CAP_STREAMING, + config.quiet); if (!test) { fprintf(stderr, "Missing required driver streaming capability\n"); goto error; @@ -383,10 +423,12 @@ int main(int argc, char *argv[]) if (selected_format->v4l2_mplane) test = video_engine_capabilities_test(video_fd, - V4L2_CAP_VIDEO_M2M_MPLANE); + V4L2_CAP_VIDEO_M2M_MPLANE, + config.quiet); else test = video_engine_capabilities_test(video_fd, - V4L2_CAP_VIDEO_M2M); + V4L2_CAP_VIDEO_M2M, + config.quiet); if (!test) { fprintf(stderr, "Missing required driver M2M capability\n"); @@ -395,7 +437,8 @@ int main(int argc, char *argv[]) rc = video_engine_start(video_fd, media_fd, width, height, selected_format, preset->type, &video_buffers, - config.buffers_count, &video_setup); + config.buffers_count, &video_setup, + config.quiet); if (rc < 0) { fprintf(stderr, "Unable to start video engine\n"); goto error; @@ -403,7 +446,7 @@ int main(int argc, char *argv[]) rc = display_engine_start(drm_fd, width, height, selected_format, video_buffers, config.buffers_count, - &gem_buffers, &display_setup); + &gem_buffers, &display_setup, config.quiet); if (rc < 0) { fprintf(stderr, "Unable to start display engine\n"); goto error; @@ -487,7 +530,7 @@ int main(int argc, char *argv[]) rc = video_engine_decode(video_fd, v4l2_index, &frame.frame, preset->type, ts, slice_data, slice_size, video_buffers, - &video_setup); + &video_setup, config.quiet); if (rc < 0) { fprintf(stderr, "Unable to decode video frame\n"); goto error; @@ -523,7 +566,8 @@ int main(int argc, char *argv[]) clock_gettime(CLOCK_MONOTONIC, &display_before); rc = display_engine_show(drm_fd, v4l2_index, video_buffers, - gem_buffers, &display_setup); + gem_buffers, &display_setup, + config.quiet); if (rc < 0) { fprintf(stderr, "Unable to display video frame\n"); goto error; @@ -564,13 +608,14 @@ int main(int argc, char *argv[]) } rc = video_engine_stop(video_fd, video_buffers, config.buffers_count, - &video_setup); + &video_setup, config.quiet); if (rc < 0) { fprintf(stderr, "Unable to stop video engine\n"); goto error; } - rc = display_engine_stop(drm_fd, gem_buffers, &display_setup); + rc = display_engine_stop(drm_fd, gem_buffers, &display_setup, + config.quiet); if (rc < 0) { fprintf(stderr, "Unable to stop display engine\n"); goto error; diff --git a/v4l2-request-test.h b/v4l2-request-test.h index 7c8a1c3..d99337d 100644 --- a/v4l2-request-test.h +++ b/v4l2-request-test.h @@ -124,6 +124,12 @@ struct preset { unsigned int display_count; }; +extern const struct codec { + char *name; + char *description; + enum codec_type type; +} codec[]; + /* V4L2 */ struct video_setup { @@ -220,19 +226,23 @@ int frame_gop_schedule(struct preset *preset, unsigned int index); /* V4L2 */ bool video_engine_capabilities_test(int video_fd, - unsigned int capabilities_required); + unsigned int capabilities_required, + bool quiet); bool video_engine_format_test(int video_fd, bool mplane, unsigned int width, - unsigned int height, unsigned int format); + unsigned int height, unsigned int format, + bool quiet); int video_engine_start(int video_fd, int media_fd, unsigned int width, unsigned int height, struct format_description *format, enum codec_type type, struct video_buffer **buffers, - unsigned int buffers_count, struct video_setup *setup); + unsigned int buffers_count, struct video_setup *setup, + bool quiet); int video_engine_stop(int video_fd, struct video_buffer *buffers, - unsigned int buffers_count, struct video_setup *setup); + unsigned int buffers_count, struct video_setup *setup, + bool quiet); int video_engine_decode(int video_fd, unsigned int index, union controls *frame, enum codec_type type, uint64_t ts, void *source_data, unsigned int source_size, struct video_buffer *buffers, - struct video_setup *setup); + struct video_setup *setup, bool quiet); /* DRM */ @@ -240,12 +250,15 @@ int display_engine_start(int drm_fd, unsigned int width, unsigned int height, struct format_description *format, struct video_buffer *video_buffers, unsigned int count, struct gem_buffer **buffers, - struct display_setup *setup); + struct display_setup *setup, + bool quiet); int display_engine_stop(int drm_fd, struct gem_buffer *buffers, - struct display_setup *setup); + struct display_setup *setup, + bool quiet); int display_engine_show(int drm_fd, unsigned int index, struct video_buffer *video_buffers, struct gem_buffer *buffers, - struct display_setup *setup); + struct display_setup *setup, + bool quiet); #endif diff --git a/v4l2.c b/v4l2.c index bcf5097..ee7cc44 100644 --- a/v4l2.c +++ b/v4l2.c @@ -30,8 +30,8 @@ #include #include #include -#include -#include +//#include +//#include #include "v4l2-request-test.h" @@ -149,7 +149,8 @@ static int try_format(int video_fd, unsigned int type, unsigned int width, } static int set_format(int video_fd, unsigned int type, unsigned int width, - unsigned int height, unsigned int pixelformat) + unsigned int height, unsigned int pixelformat, + bool quiet) { struct v4l2_format format; int rc; @@ -431,7 +432,7 @@ static int export_buffer(int video_fd, unsigned int type, unsigned int index, } static int set_control(int video_fd, int request_fd, unsigned int id, - void *data, unsigned int size) + void *data, unsigned int size, bool quiet) { struct v4l2_ext_control control; struct v4l2_ext_controls controls; @@ -452,9 +453,18 @@ static int set_control(int video_fd, int request_fd, unsigned int id, controls.request_fd = request_fd; } + if (!quiet) { + /* Ref: https://www.kernel.org/doc/html/v4.10/media/uapi/v4l/vidioc-g-ext-ctrls.html */ + fprintf(stderr, "Initialized 'controls' structure (ctrl_class: %d, which: %d)\n", + controls.ctrl_class, controls.which); + fprintf(stderr, " 'control' value (id: %d, size: %d)\n", + control.id, control.size); + } + rc = ioctl(video_fd, VIDIOC_S_EXT_CTRLS, &controls); if (rc < 0) { - fprintf(stderr, "Unable to set control: %s\n", strerror(errno)); + fprintf(stderr, "Unable to set control: %s (%d)\n", + strerror(errno), errno); return -1; } @@ -478,7 +488,8 @@ static int set_stream(int video_fd, unsigned int type, bool enable) } static int set_format_controls(int video_fd, int request_fd, - enum codec_type type, union controls *frame) + enum codec_type type, union controls *frame, + bool quiet) { struct { enum codec_type type; @@ -509,7 +520,7 @@ static int set_format_controls(int video_fd, int request_fd, V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX, &frame->h264.scaling_matrix, sizeof(frame->h264.scaling_matrix) }, - { CODEC_TYPE_H264, "scaling matrix", + { CODEC_TYPE_H264, "slice parameters", V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS, &frame->h264.slice_param, sizeof(frame->h264.slice_param) }, #endif @@ -525,15 +536,41 @@ static int set_format_controls(int video_fd, int request_fd, &frame->h265.slice_params, sizeof(frame->h265.slice_params) }, #endif }; + struct codec codec[] = { + { + .name = "MPEG-2", + .description = "Moving Pictures Expert Group Version-4 (MPEG-2)", + .type = CODEC_TYPE_MPEG2, + }, + { + .name = "H.264", + .description = "Moving Pictures Expert Group Version-4 (MPEG-4)", + .type = CODEC_TYPE_MPEG2, + }, + { + .name = "H.265", + .description = "High-Efficiency Video Coding (HEVC)", + .type = CODEC_TYPE_MPEG2, + }, + }; unsigned int i; int rc; for (i = 0; i < ARRAY_SIZE(glue); i++) { - if (glue[i].type != type) + if (glue[i].type != type) { + if (!quiet) + fprintf(stderr, "Skipping codec %s->%s\n", + codec[glue[i].type].name, glue[i].description); continue; + } + if (!quiet) + fprintf(stderr, "size of decode_params: %d\n", + glue[i].size); + fprintf(stderr, "data: %d\n", + glue[i].data); rc = set_control(video_fd, request_fd, glue[i].id, glue[i].data, - glue[i].size); + glue[i].size, quiet); if (rc < 0) { fprintf(stderr, "Unable to set %s control\n", glue[i].description); @@ -564,11 +601,15 @@ static int codec_source_format(enum codec_type type) } bool video_engine_capabilities_test(int video_fd, - unsigned int capabilities_required) + unsigned int capabilities_required, + bool quiet) { unsigned int capabilities; int rc; + if(!quiet) + fprintf(stderr, "video_engine_capabilities_test ...\n"); + rc = query_capabilities(video_fd, &capabilities); if (rc < 0) { fprintf(stderr, "Unable to query video capabilities: %s\n", @@ -583,11 +624,15 @@ bool video_engine_capabilities_test(int video_fd, } bool video_engine_format_test(int video_fd, bool mplane, unsigned int width, - unsigned int height, unsigned int format) + unsigned int height, unsigned int format, + bool quiet) { unsigned int type; int rc; + if(!quiet) + fprintf(stderr, "video_engine_format_test ...\n"); + type = mplane ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -599,7 +644,8 @@ bool video_engine_format_test(int video_fd, bool mplane, unsigned int width, int video_engine_start(int video_fd, int media_fd, unsigned int width, unsigned int height, struct format_description *format, enum codec_type type, struct video_buffer **buffers, - unsigned int buffers_count, struct video_setup *setup) + unsigned int buffers_count, struct video_setup *setup, + bool quiet) { struct video_buffer *buffer; unsigned int source_format; @@ -635,7 +681,11 @@ int video_engine_start(int video_fd, int media_fd, unsigned int width, source_format = codec_source_format(type); - rc = set_format(video_fd, output_type, width, height, source_format); + if(!quiet) + fprintf(stderr, "video_engine_start ...\n"); + + rc = set_format(video_fd, output_type, width, height, + source_format, quiet); if (rc < 0) { fprintf(stderr, "Unable to set source format\n"); goto error; @@ -644,7 +694,7 @@ int video_engine_start(int video_fd, int media_fd, unsigned int width, destination_format = format->v4l2_format; rc = set_format(video_fd, capture_type, width, height, - destination_format); + destination_format, quiet); if (rc < 0) { fprintf(stderr, "Unable to set destination format\n"); goto error; @@ -822,7 +872,8 @@ int video_engine_start(int video_fd, int media_fd, unsigned int width, } int video_engine_stop(int video_fd, struct video_buffer *buffers, - unsigned int buffers_count, struct video_setup *setup) + unsigned int buffers_count, struct video_setup *setup, + bool quiet) { unsigned int i, j; int rc; @@ -871,7 +922,7 @@ int video_engine_stop(int video_fd, struct video_buffer *buffers, int video_engine_decode(int video_fd, unsigned int index, union controls *frame, enum codec_type type, uint64_t ts, void *source_data, unsigned int source_size, struct video_buffer *buffers, - struct video_setup *setup) + struct video_setup *setup, bool quiet) { struct timeval tv = { 0, 300000 }; int request_fd = -1; @@ -880,10 +931,17 @@ int video_engine_decode(int video_fd, unsigned int index, union controls *frame, int rc; request_fd = buffers[index].request_fd; + if(!quiet) { + fprintf(stderr, "video_engine_decode ...\n"); + fprintf(stderr, " video_fd: %d\n", + video_fd); + fprintf(stderr, " request_fd: %d\n", + request_fd); + } memcpy(buffers[index].source_data, source_data, source_size); - rc = set_format_controls(video_fd, request_fd, type, frame); + rc = set_format_controls(video_fd, request_fd, type, frame, quiet); if (rc < 0) { fprintf(stderr, "Unable to set format controls\n"); return -1;