diff options
| -rw-r--r-- | v4l2-jpeg-codec-test/Makefile | 30 | ||||
| -rw-r--r-- | v4l2-jpeg-codec-test/README | 37 | ||||
| -rw-r--r-- | v4l2-jpeg-codec-test/run_fmt_test.sh | 33 | ||||
| -rw-r--r-- | v4l2-jpeg-codec-test/test-jpeg.c | 574 | 
4 files changed, 674 insertions, 0 deletions
diff --git a/v4l2-jpeg-codec-test/Makefile b/v4l2-jpeg-codec-test/Makefile new file mode 100644 index 0000000..715f398 --- /dev/null +++ b/v4l2-jpeg-codec-test/Makefile @@ -0,0 +1,30 @@ +# Target root +TARGETROOT?= +# Toolchain path +TCPATH?=arm-linux-gnueabi- + +CC = ${TCPATH}gcc +AR = "${TCPATH}ar rc" +AR2 = ${TCPATH}ranlib make -j4 + +INCLUDES = -I$(TARGETROOT)/include +SOURCES = test-jpeg.c +OBJECTS := $(SOURCES:.c=.o) +EXEC = test-jpeg +CFLAGS = -Wall -g + +all: $(EXEC) + +.c.o: +	$(CC) -c $(CFLAGS) $(INCLUDES) $< + +$(EXEC): $(OBJECTS) +	$(CC) $(CFLAGS) -g -O0 -o $(EXEC) $(OBJECTS) -lpthread + +clean: +	rm -f *.o $(EXEC) + +install: + + +.PHONY: clean all diff --git a/v4l2-jpeg-codec-test/README b/v4l2-jpeg-codec-test/README new file mode 100644 index 0000000..bbfe811 --- /dev/null +++ b/v4l2-jpeg-codec-test/README @@ -0,0 +1,37 @@ +/* + * JPEG codec encoding example application + * Jacek Anaszewski <j.anaszewski@samsung.com> + * + * Copyright 2011 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +The run_fmt_test.sh script decodes the input JPEG file to raw format and +encodes the raw file to the JPEG format. This procedure is repeated for +all the formats supported by the driver. + +Build +----- + +1. Install kernel headers, for details see +https://www.kernel.org/doc/Documentation/make/headers_install.txt +E.g., in kernel root directory: +  make headers_install ARCH=arm INSTALL_HDR_PATH=~/rootdir + +2. Build the application, e.g. +  make TARGETROOT=~/rootdir + +The arguments required by the script: + - name of the JPEG file to be decoded diff --git a/v4l2-jpeg-codec-test/run_fmt_test.sh b/v4l2-jpeg-codec-test/run_fmt_test.sh new file mode 100644 index 0000000..4f41f81 --- /dev/null +++ b/v4l2-jpeg-codec-test/run_fmt_test.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +formats=(FMT_JPEG +	 FMT_RGB565 +         FMT_RGB32 +         FMT_YUYV +         FMT_YVYU +         FMT_NV24 +         FMT_NV42 +         FMT_NV16 +         FMT_NV61 +         FMT_NV12 +         FMT_NV21 +         FMT_YUV420 +	 FMT_GRAY) + +CNT=1 +JPEG_ENC_NODE=`dmesg | awk '/s5p-jpeg.*encoder/ {print substr($0, length($0), 1)}'` +JPEG_DEC_NODE=`dmesg | awk '/s5p-jpeg.*decoder/ {print substr($0, length($0), 1)}'` + +while [ $CNT -ne ${#formats[@]} ] +do +	echo "============== jpeg -> "${formats[$CNT]}" ==============" + +	./test-jpeg -m1 -f$1 -oout_${formats[$CNT]}.raw -v$JPEG_DEC_NODE -r$CNT | tee out_dec +	WIDTH=`cat out_dec | awk '/output image dimensions/ {print $4}' | awk -Fx '{print $1}'` +	HEIGHT=`cat out_dec | awk '/output image dimensions/ {print $4}' | awk -Fx '{print $2}'` +	echo "parsed: "$WIDTH"x"$HEIGHT + +	echo "============== "${formats[$CNT]}" -> jpeg ==============" +	./test-jpeg -m0 -fout_${formats[$CNT]}.raw -oout_${formats[$CNT]}.jpeg -w$WIDTH -h$HEIGHT -v$JPEG_ENC_NODE -r$CNT -c0 -p0 +	(( CNT++ )) +done diff --git a/v4l2-jpeg-codec-test/test-jpeg.c b/v4l2-jpeg-codec-test/test-jpeg.c new file mode 100644 index 0000000..6acb204 --- /dev/null +++ b/v4l2-jpeg-codec-test/test-jpeg.c @@ -0,0 +1,574 @@ + /* +  * test-jpeg.c +  * +  * Copyright 2011 - 2013 Samsung Electronics Co., Ltd. +  * +  * Licensed under the Apache License, Version 2.0 (the "License"); +  * you may not use this file except in compliance with the License. +  * You may obtain a copy of the License atoi * +  * http://www.apache.org/licenses/LICENSE-2.0 * +  * Unless required by applicable law or agreed to in writing, Software +  * distributed under the License is distributed on an "AS IS" BASIS, +  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +  * See the License for the specific language governing permissions and +  * limitations under the License. +  * +  */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <time.h> +#include <errno.h> +#include <ctype.h> + +#include <fcntl.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdint.h> + +#include <linux/fb.h> +#include <linux/videodev2.h> + +#include <sys/mman.h> + +#define VIDEO_DEV_NAME	"/dev/video" + +#define perror_exit(cond, func)\ +	if (cond) {\ +		fprintf(stderr, "%s:%d: ", __func__, __LINE__);\ +		perror(func);\ +		exit(EXIT_FAILURE);\ +	} + +#define perror_ret(cond, func)\ +	if (cond) {\ +		fprintf(stderr, "%s:%d: ", __func__, __LINE__);\ +		perror(func);\ +		return ret;\ +	} + +#define memzero(x)\ +	memset(&(x), 0, sizeof (x)); + + +//#define PROCESS_DEBUG +#ifdef PROCESS_DEBUG +#define debug(msg, ...)\ +	fprintf(stderr, "%s: \n" msg, __func__, ##__VA_ARGS__); +#else +#define debug(msg, ...) +#endif + +#define ENCODE 0 +#define DECODE 1 + +enum pix_format { +	FMT_JPEG, +        FMT_RGB565, +        FMT_RGB32, +        FMT_YUYV, +        FMT_YVYU, +        FMT_NV24, +        FMT_NV42, +        FMT_NV16, +        FMT_NV61, +        FMT_NV12, +        FMT_NV21, +        FMT_YUV420, +        FMT_GREY, +}; + +static int vid_fd; +static char *p_src_buf, *p_dst_buf; +static char *p_input_file; +static size_t src_buf_size, dst_buf_size; +static int input_file_sz, capture_buffer_sz = 0, compr_quality = 0, subsampling, +	   num_src_bufs, num_dst_bufs; + +/* Command-line params */ +int mode = ENCODE; +const char *input_filename; +const char *output_filename; +int video_node = 5; +int width = 0, height = 0; +int fourcc; + +static __u32 get_px_format_by_id(enum pix_format px_fmt) +{ +        switch (px_fmt) { +	case FMT_JPEG: +		return V4L2_PIX_FMT_JPEG; +	case FMT_RGB565: +		return V4L2_PIX_FMT_RGB565; +	case FMT_RGB32: +		return V4L2_PIX_FMT_RGB32; +	case FMT_YUYV: +		return V4L2_PIX_FMT_YUYV; +	case FMT_YVYU: +		return V4L2_PIX_FMT_YVYU; +	case FMT_NV24: +		return V4L2_PIX_FMT_NV24; +	case FMT_NV42: +		return V4L2_PIX_FMT_NV42; +	case FMT_NV16: +		return V4L2_PIX_FMT_NV16; +	case FMT_NV61: +		return V4L2_PIX_FMT_NV61; +	case FMT_NV12: +		return V4L2_PIX_FMT_NV12; +	case FMT_NV21: +		return V4L2_PIX_FMT_NV21; +	case FMT_YUV420: +		return V4L2_PIX_FMT_YUV420; +	case FMT_GREY: +		return V4L2_PIX_FMT_GREY; +        } + +        return -EINVAL; +} + +static void get_format_name_by_fourcc(unsigned int fourcc, char *fmt_name) +{ +        switch (fourcc) { +	case V4L2_PIX_FMT_JPEG: +		strcpy(fmt_name, "V4L2_PIX_FMT_JPEG"); +		break; +	case V4L2_PIX_FMT_RGB565: +		strcpy(fmt_name, "V4L2_PIX_FMT_RGB565"); +		break; +	case V4L2_PIX_FMT_RGB32: +		strcpy(fmt_name, "V4L2_PIX_FMT_RGB32"); +		break; +	case V4L2_PIX_FMT_YUYV: +		strcpy(fmt_name, "V4L2_PIX_FMT_YUYV"); +		break; +	case V4L2_PIX_FMT_YVYU: +		strcpy(fmt_name, "V4L2_PIX_FMT_YVYU"); +		break; +	case V4L2_PIX_FMT_NV24: +		strcpy(fmt_name, "V4L2_PIX_FMT_NV24"); +		break; +	case V4L2_PIX_FMT_NV42: +		strcpy(fmt_name, "V4L2_PIX_FMT_NV42"); +		break; +	case V4L2_PIX_FMT_NV16: +		strcpy(fmt_name, "V4L2_PIX_FMT_NV16"); +		break; +	case V4L2_PIX_FMT_NV61: +		strcpy(fmt_name, "V4L2_PIX_FMT_NV61"); +		break; +	case V4L2_PIX_FMT_NV12: +		strcpy(fmt_name, "V4L2_PIX_FMT_NV12"); +		break; +	case V4L2_PIX_FMT_NV21: +		strcpy(fmt_name, "V4L2_PIX_FMT_NV21"); +		break; +	case V4L2_PIX_FMT_YUV420: +		strcpy(fmt_name, "V4L2_PIX_FMT_YUV420"); +		break; +	case V4L2_PIX_FMT_GREY: +		strcpy(fmt_name, "V4L2_PIX_FMT_GREY"); +		break; +	default: +		strcpy(fmt_name, "UNKNOWN"); +		break; +        } +} + +static void get_subsampling_by_id(int subs, char *subs_name) +{ +	switch (subs) { +	case V4L2_JPEG_CHROMA_SUBSAMPLING_444: +		strcpy(subs_name, "JPEG 4:4:4"); +		break; +	case V4L2_JPEG_CHROMA_SUBSAMPLING_422: +		strcpy(subs_name, "JPEG 4:2:2"); +		break; +	case V4L2_JPEG_CHROMA_SUBSAMPLING_420: +		strcpy(subs_name, "JPEG 4:2:0"); +		break; +	case V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY: +		strcpy(subs_name, "GRAY SCALE JPEG"); +		break; +	default: +		sprintf(subs_name, "Unknown JPEG subsampling: %d", subs); +		break; +	} +} + +static int dq_frame(void) +{ +	struct v4l2_buffer buf; +	int ret; + +	memzero(buf); + +	buf.type	= V4L2_BUF_TYPE_VIDEO_OUTPUT; +	buf.memory	= V4L2_MEMORY_MMAP; +	ret = ioctl(vid_fd, VIDIOC_DQBUF, &buf); +	debug("Dequeued source buffer, index: %d\n", buf.index); +	if (ret) { +		switch (errno) { +		case EAGAIN: +			debug("Got EAGAIN\n"); +			return 0; + +		case EIO: +			debug("Got EIO\n"); +			return 0; + +		default: +			perror("ioctl"); +			return 0; +		} +	} + +	/* Verify we've got a correct buffer */ +	assert(buf.index < num_src_bufs); + +	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +	ret = ioctl(vid_fd, VIDIOC_DQBUF, &buf); +	debug("Dequeued dst buffer, index: %d\n", buf.index); +	if (ret) { +		switch (errno) { +		case EAGAIN: +			debug("Got EAGAIN\n"); +			return 0; + +		case EIO: +			debug("Got EIO\n"); +			return 0; + +		default: +			perror("ioctl"); +			return 1; +		} +	} + +	/* Verify we've got a correct buffer */ +	assert(buf.index < num_dst_bufs); + +	capture_buffer_sz = buf.bytesused; +	return 0; +} + +int init_input_file(void) +{ +	struct stat stat; +	int fd; + +	fd = open(input_filename, O_RDONLY); +	fstat(fd, &stat); +	input_file_sz = stat.st_size; +	printf("input_file size: %d\n", input_file_sz); + +	p_input_file = mmap(NULL, input_file_sz, PROT_READ , MAP_SHARED, fd, 0); + +	return fd; +} + + +void print_usage (void) +{ +	fprintf (stderr, "Usage:\n" +		 "-m[MODE: 0 - ENCODE, 1 - DECODE]\n" +		 "-f[INPUT FILE NAME]\n" +		 "-o[OUTPUT FILE NAME]\n" +		 "-v[VIDEO NODE NUMBER]\n" +		 "-w[INPUT IMAGE WIDTH]\n" +		 "-h[INPUT IMAGE HEIGHT]\n" +		 "-r[COLOUR FORMAT: 1..12]\n" +		 "-c[COMPRESSION LEVEL: 0..3]\n" +		 "-p[CHROMA SUBSAMPLING: 0..3]\n"); +} + +static int parse_args(int argc, char *argv[]) +{ +	int c; + +	opterr = 0; +	while ((c = getopt (argc, argv, "m:f:o:v:w:h:r:c:p:")) != -1) { +		debug("c: %c, optarg: %s\n", c, optarg); +		switch (c) { +		case 'm': +			mode = atoi(optarg); +			break; +		case 'f': +			input_filename = optarg; +			break; +		case 'o': +			output_filename = optarg; +			break; +		case 'v': +			video_node = atoi(optarg); +			break; +		case 'w': +			width = atoi(optarg); +			break; +		case 'h': +			height = atoi(optarg); +			break; +		case 'r': +			fourcc = atoi(optarg); +			break; +		case 'c': +			compr_quality = atoi(optarg); +			break; +		case 'p': +			subsampling = atoi(optarg); +			break; +		case '?': +			print_usage (); +			return -1; +		default: +			fprintf (stderr, +				 "Unknown option character `\\x%x'.\n", +				 optopt); +			return -1; +		} +	} + +//	printf("mode: %d, input_filename: %s, video_node: %s%d, width: %d, height: %d, fourcc: %d, compr_quality: %d, subsampling: %d\n", +//		mode, input_filename, VIDEO_DEV_NAME, video_node, width, height, fourcc, compr_quality, subsampling); +	return 0; +} + +int main(int argc, char *argv[]) +{ +	int i, r, input_fd; +	int ret = 0; +	struct v4l2_buffer buf; +	struct v4l2_requestbuffers reqbuf; +	enum v4l2_buf_type type; +	fd_set read_fds; +	char *def_outfile = "out.file"; + +	struct v4l2_capability cap; +	struct v4l2_format fmt; +	char video_node_name[20]; + +	ret = parse_args(argc, argv); +	if (ret < 0) +		return 0; + +	input_fd = init_input_file(); +	memzero(reqbuf); + +	strcpy(video_node_name, VIDEO_DEV_NAME); +	sprintf(video_node_name + strlen(video_node_name), "%d", video_node); +	vid_fd = open(video_node_name, O_RDWR | O_NONBLOCK, 0); +	perror_exit(vid_fd < 0, "open"); + +	ret = ioctl(vid_fd, VIDIOC_QUERYCAP, &cap); +	perror_exit(ret != 0, "ioctl"); + +	if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { +		fprintf(stderr, "Device does not support capture\n"); +		exit(EXIT_FAILURE); +	} +	if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) { +		fprintf(stderr, "Device does not support output\n"); +		exit(EXIT_FAILURE); +	} + +	/* set input format */ +	fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; +	fmt.fmt.pix.width	= width; +	fmt.fmt.pix.height	= height; +	fmt.fmt.pix.sizeimage	= input_file_sz; +	if (mode == ENCODE) +		fmt.fmt.pix.pixelformat = get_px_format_by_id(fourcc); +	else +		fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; +	fmt.fmt.pix.field	= V4L2_FIELD_ANY; +	fmt.fmt.pix.bytesperline = 0; + +	ret = ioctl(vid_fd, VIDIOC_S_FMT, &fmt); +	perror_exit(ret != 0, "ioctl"); + +	/* request input buffer */ +	reqbuf.count	= 1; +	reqbuf.type	= V4L2_BUF_TYPE_VIDEO_OUTPUT; +	reqbuf.memory	= V4L2_MEMORY_MMAP; + +	ret = ioctl(vid_fd, VIDIOC_REQBUFS, &reqbuf); +	perror_exit(ret != 0, "ioctl"); +	num_src_bufs = reqbuf.count; + +	/* query buffer parameters */ +	buf.type	= V4L2_BUF_TYPE_VIDEO_OUTPUT; +	buf.memory	= V4L2_MEMORY_MMAP; +	buf.index	= 0; + +	ret = ioctl(vid_fd, VIDIOC_QUERYBUF, &buf); +	perror_exit(ret != 0, "ioctl"); + +	src_buf_size = buf.length; + +	/* mmap buffer */ +	p_src_buf = mmap(NULL, buf.length, +			    PROT_READ | PROT_WRITE, MAP_SHARED, +			    vid_fd, buf.m.offset); +	perror_exit(MAP_FAILED == p_src_buf, "mmap"); + +	/* copy input file data to the buffer */ +	memcpy(p_src_buf, p_input_file, input_file_sz); + +	/* queue input buffer */ +	memzero(buf); +	buf.type	= V4L2_BUF_TYPE_VIDEO_OUTPUT; +	buf.memory	= V4L2_MEMORY_MMAP; +	buf.index	= 0; + +	ret = ioctl(vid_fd, VIDIOC_QBUF, &buf); +	perror_exit(ret != 0, "ioctl"); + +	type = V4L2_BUF_TYPE_VIDEO_OUTPUT; +	ret = ioctl(vid_fd, VIDIOC_STREAMON, &type); +	perror_exit(ret != 0, "ioctl"); + +	if (mode == DECODE) { +		/* get input JPEG dimensions */ +		fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +		ret = ioctl(vid_fd, VIDIOC_G_FMT, &fmt); +		perror_exit(ret != 0, "ioctl"); +		width = fmt.fmt.pix.width; +		height = fmt.fmt.pix.height; +		printf("input JPEG dimensions: %dx%d\n", width, height); +	} + +	/* set output format */ +	fmt.type		= V4L2_BUF_TYPE_VIDEO_CAPTURE; +	fmt.fmt.pix.width	= width; +	fmt.fmt.pix.height	= height; +	fmt.fmt.pix.sizeimage	= width * height * 4; +	if (mode == DECODE) +		fmt.fmt.pix.pixelformat = get_px_format_by_id(fourcc); +	else +		fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; +	fmt.fmt.pix.field	= V4L2_FIELD_ANY; + +	char fmt_name[30]; +	get_format_name_by_fourcc(fmt.fmt.pix.pixelformat, fmt_name); +	printf("setting output format: %s\n", fmt_name); + +	ret = ioctl(vid_fd, VIDIOC_S_FMT, &fmt); +	perror_exit(ret != 0, "ioctl"); + +	get_format_name_by_fourcc(fmt.fmt.pix.pixelformat, fmt_name); +	printf("output format set: %s\n", fmt_name); +	printf("output image dimensions: %dx%d\n", fmt.fmt.pix.width, fmt.fmt.pix.height); + +	if (mode == ENCODE) { +		struct v4l2_ext_controls ctrls; +		struct v4l2_ext_control ctrl[2]; +		int ret; + +		/* set compression quality */ +		memzero(ctrl[0]); +		memzero(ctrl[1]); +		memzero(ctrls); + +		ctrl[0].id = V4L2_CID_JPEG_COMPRESSION_QUALITY; +		ctrl[0].value = compr_quality; + +		ctrl[1].id = V4L2_CID_JPEG_CHROMA_SUBSAMPLING; +		ctrl[1].value = subsampling; + +		ctrls.ctrl_class = V4L2_CTRL_CLASS_JPEG; +		ctrls.count = 2; +		ctrls.controls = ctrl; + +		ret = ioctl (vid_fd, VIDIOC_S_EXT_CTRLS, &ctrls); +		perror_exit (ret != 0, "VIDIOC_S_CTRL v4l2_ioctl"); +	} + +	/* request output buffer */ +	reqbuf.count = 1; +	reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +	ret = ioctl(vid_fd, VIDIOC_REQBUFS, &reqbuf); +	perror_exit(ret != 0, "ioctl"); +	num_dst_bufs = reqbuf.count; + +	/* query buffer parameters */ +	buf.type	= V4L2_BUF_TYPE_VIDEO_CAPTURE; +	buf.memory	= V4L2_MEMORY_MMAP; +	buf.index	= 0; + +	ret = ioctl(vid_fd, VIDIOC_QUERYBUF, &buf); +	perror_exit(ret != 0, "ioctl"); + +	/* mmap buffer */ +	p_dst_buf = mmap(NULL, buf.length, +			    PROT_READ | PROT_WRITE, MAP_SHARED, +			    vid_fd, buf.m.offset); +	perror_exit(MAP_FAILED == p_dst_buf, "mmap"); + +	memzero(buf); +	buf.type	= V4L2_BUF_TYPE_VIDEO_CAPTURE; +	buf.memory	= V4L2_MEMORY_MMAP; +	buf.index	= 0; + +	ret = ioctl(vid_fd, VIDIOC_QBUF, &buf); +	perror_exit(ret != 0, "ioctl"); + +	type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +	ret = ioctl(vid_fd, VIDIOC_STREAMON, &type); +	perror_exit(ret != 0, "ioctl"); + +	/* dequeue buffer */ +	FD_ZERO(&read_fds); +	FD_SET(vid_fd, &read_fds); + +	r = select(vid_fd + 1, &read_fds, NULL, NULL, 0); +	perror_exit(r < 0, "select"); + +	if (dq_frame()) { +		fprintf(stderr, "dequeue frame failed\n"); +		goto done; +	} + +	if (mode == DECODE) { +		struct v4l2_control ctrl; +		char subs_name[50]; + +		/* get input JPEG subsampling info */ +		memzero(ctrl); +		ctrl.id = V4L2_CID_JPEG_CHROMA_SUBSAMPLING; + +		ret = ioctl (vid_fd, VIDIOC_G_CTRL, &ctrl); +		perror_exit (ret != 0, "VIDIOC_G_CTRL v4l2_ioctl"); + +		get_subsampling_by_id(ctrl.value, subs_name); +		printf("decoded JPEG subsampling: %s\n", subs_name); +	} + +	/* generate output file */ +	if (output_filename == NULL) +		output_filename = def_outfile; + +	int out_fd = open(output_filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); + +	printf("Generating output file...\n"); +	char x; +	for (i = 0; i < capture_buffer_sz; ++i) { +		x = p_dst_buf[i]; +		write(out_fd, (const void * )&x, 1); +	} +	close(out_fd); + +	printf("Output file: %s, size: %d\n", output_filename, capture_buffer_sz); + +done: +	close(vid_fd); +	close(input_fd); +	munmap(p_src_buf, src_buf_size); +	munmap(p_dst_buf, dst_buf_size); +	munmap(p_input_file, input_file_sz); + +	return ret; +} +  | 
