[PATCH] v4l2-ctl: add is_compressed_format() helper

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



It is used to:

  bypass precalculate_bars() for OUTPUT device
  that takes encoded bitstreams.

  handle the last chunk of input file that has
  non-buffer-aligned size.

Signed-off-by: Tzu-Jung Lee <tjlee@xxxxxxxxxxxxx>
---
 utils/v4l2-ctl/v4l2-ctl-streaming.cpp | 132 ++++++++++++++++++++++++++++------
 1 file changed, 112 insertions(+), 20 deletions(-)

diff --git a/utils/v4l2-ctl/v4l2-ctl-streaming.cpp b/utils/v4l2-ctl/v4l2-ctl-streaming.cpp
index 9e361af..44643e8 100644
--- a/utils/v4l2-ctl/v4l2-ctl-streaming.cpp
+++ b/utils/v4l2-ctl/v4l2-ctl-streaming.cpp
@@ -115,6 +115,29 @@ static const flag_def tc_flags_def[] = {
 	{ 0, NULL }
 };
 
+static bool is_compressed_format(__u32 pixfmt)
+{
+	switch (pixfmt) {
+	case V4L2_PIX_FMT_MJPEG:
+	case V4L2_PIX_FMT_JPEG:
+	case V4L2_PIX_FMT_DV:
+	case V4L2_PIX_FMT_MPEG:
+	case V4L2_PIX_FMT_H264:
+	case V4L2_PIX_FMT_H264_NO_SC:
+	case V4L2_PIX_FMT_H263:
+	case V4L2_PIX_FMT_MPEG1:
+	case V4L2_PIX_FMT_MPEG2:
+	case V4L2_PIX_FMT_MPEG4:
+	case V4L2_PIX_FMT_XVID:
+	case V4L2_PIX_FMT_VC1_ANNEX_G:
+		return true;
+	default:
+		return false;
+	}
+
+	return false;
+}
+
 static void print_buffer(FILE *f, struct v4l2_buffer &buf)
 {
 	fprintf(f, "\tIndex    : %d\n", buf.index);
@@ -223,25 +246,60 @@ void streaming_cmd(int ch, char *optarg)
 }
 
 static bool fill_buffer_from_file(void *buffers[], unsigned buffer_lengths[],
-		unsigned buf_index, unsigned num_planes, FILE *fin)
+				  unsigned buffer_bytesused[], unsigned buf_index,
+				  unsigned num_planes, bool is_compressed, FILE *fin)
 {
+	if (num_planes == 1) {
+		unsigned i = buf_index;
+		unsigned sz = fread(buffers[i], 1,
+				    buffer_lengths[i], fin);
+
+		buffer_bytesused[i] = sz;
+		if (sz == 0 && stream_loop) {
+			fseek(fin, 0, SEEK_SET);
+			sz = fread(buffers[i], 1,
+				   buffer_lengths[i], fin);
+
+			buffer_bytesused[i] = sz;
+		}
+
+		if (!sz)
+			return false;
+
+		if (sz == buffer_lengths[i])
+			return true;
+
+		if (is_compressed)
+			return true;
+
+		fprintf(stderr, "%u != %u\n", sz, buffer_lengths[i]);
+
+		return false;
+	}
+
 	for (unsigned j = 0; j < num_planes; j++) {
 		unsigned p = buf_index * num_planes + j;
 		unsigned sz = fread(buffers[p], 1,
-				buffer_lengths[p], fin);
+				    buffer_lengths[p], fin);
 
+		buffer_bytesused[j] = sz;
 		if (j == 0 && sz == 0 && stream_loop) {
 			fseek(fin, 0, SEEK_SET);
 			sz = fread(buffers[p], 1,
-					buffer_lengths[p], fin);
+				   buffer_lengths[p], fin);
+
+			buffer_bytesused[j] = sz;
 		}
 		if (sz == buffer_lengths[p])
 			continue;
+
+		// Bail out if we get weird buffer sizes.
 		if (sz)
 			fprintf(stderr, "%u != %u\n", sz, buffer_lengths[p]);
-		// Bail out if we get weird buffer sizes.
+
 		return false;
 	}
+
 	return true;
 }
 
@@ -312,16 +370,22 @@ static void do_setup_out_buffers(int fd, struct v4l2_requestbuffers *reqbufs,
 				 bool is_mplane, unsigned &num_planes, bool is_mmap,
 				 void *buffers[], unsigned buffer_lengths[], FILE *fin)
 {
+	bool is_compressed;
+
 	struct v4l2_format fmt;
 	memset(&fmt, 0, sizeof(fmt));
 	fmt.type = reqbufs->type;
 	doioctl(fd, VIDIOC_G_FMT, &fmt);
 
-	if (!precalculate_bars(fmt.fmt.pix.pixelformat, stream_pat)) {
+	is_compressed = is_compressed_format(fmt.fmt.pix.pixelformat);
+	if (!is_compressed &&
+	    !precalculate_bars(fmt.fmt.pix.pixelformat, stream_pat)) {
 		fprintf(stderr, "unsupported pixelformat\n");
 		return;
 	}
 
+	unsigned buffer_bytesused[reqbufs->count * VIDEO_MAX_PLANES];
+
 	for (unsigned i = 0; i < reqbufs->count; i++) {
 		struct v4l2_plane planes[VIDEO_MAX_PLANES];
 		struct v4l2_buffer buf;
@@ -363,11 +427,11 @@ static void do_setup_out_buffers(int fd, struct v4l2_requestbuffers *reqbufs,
 			// TODO fill_buffer_mp(buffers[i], &fmt.fmt.pix_mp);
 			if (fin)
 				fill_buffer_from_file(buffers, buffer_lengths,
-						      buf.index, num_planes, fin);
+						      buffer_bytesused, buf.index,
+						      num_planes, is_compressed, fin);
 		}
 		else {
 			buffer_lengths[i] = buf.length;
-			buf.bytesused = buf.length;
 			if (is_mmap) {
 				buffers[i] = mmap(NULL, buf.length,
 						  PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
@@ -381,9 +445,16 @@ static void do_setup_out_buffers(int fd, struct v4l2_requestbuffers *reqbufs,
 				buffers[i] = calloc(1, buf.length);
 				buf.m.userptr = (unsigned long)buffers[i];
 			}
-			if (!fin || !fill_buffer_from_file(buffers, buffer_lengths,
-							   buf.index, num_planes, fin))
+
+			if (fin && fill_buffer_from_file(buffers, buffer_lengths,
+							 buffer_bytesused, buf.index,
+							 num_planes, is_compressed,
+							 fin)) {
+				buf.bytesused = buffer_bytesused[buf.index];
+			}
+			else {
 				fill_buffer(buffers[i], &fmt.fmt.pix);
+			}
 		}
 		if (doioctl(fd, VIDIOC_QBUF, &buf))
 			return;
@@ -511,12 +582,13 @@ static int do_handle_cap(int fd, struct v4l2_requestbuffers *reqbufs,
 }
 
 static int do_handle_out(int fd, struct v4l2_requestbuffers *reqbufs,
-			 bool is_mplane, unsigned num_planes,
+			 bool is_compressed, bool is_mplane, unsigned num_planes,
 			 void *buffers[], unsigned buffer_lengths[], FILE *fin,
 			 unsigned &count, unsigned &last, struct timeval &tv_last)
 {
 	struct v4l2_plane planes[VIDEO_MAX_PLANES];
 	struct v4l2_buffer buf;
+	unsigned buffer_bytesused[reqbufs->count * VIDEO_MAX_PLANES];
 	int ret;
 
 	memset(&buf, 0, sizeof(buf));
@@ -535,14 +607,17 @@ static int do_handle_out(int fd, struct v4l2_requestbuffers *reqbufs,
 		fprintf(stderr, "%s: failed: %s\n", "VIDIOC_DQBUF", strerror(errno));
 		return -1;
 	}
-	if (fin && !fill_buffer_from_file(buffers, buffer_lengths,
-					  buf.index, num_planes, fin))
+	if (fin &&!fill_buffer_from_file(buffers, buffer_lengths,
+					 buffer_bytesused, buf.index,
+					 num_planes, is_compressed,
+					 fin)) {
 		return -1;
+	}
 	if (is_mplane) {
 		for (unsigned j = 0; j < buf.length; j++)
-			buf.m.planes[j].bytesused = buf.m.planes[j].length;
+			buf.m.planes[j].bytesused = buffer_bytesused[j];
 	} else {
-		buf.bytesused = buf.length;
+		buf.bytesused = buffer_bytesused[buf.index];
 	}
 	if (test_ioctl(fd, VIDIOC_QBUF, &buf))
 		return -1;
@@ -688,7 +763,9 @@ static void streaming_set_cap(int fd)
 static void streaming_set_out(int fd)
 {
 	struct v4l2_requestbuffers reqbufs;
+	struct v4l2_format fmt;
 	int fd_flags = fcntl(fd, F_GETFL);
+	bool is_compressed;
 	bool is_mplane = capabilities &
 			(V4L2_CAP_VIDEO_OUTPUT_MPLANE |
 				 V4L2_CAP_VIDEO_M2M_MPLANE);
@@ -710,6 +787,12 @@ static void streaming_set_out(int fd)
 	reqbufs.type = type;
 	reqbufs.memory = is_mmap ? V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR;
 
+	memset(&fmt, 0, sizeof(fmt));
+	fmt.type = reqbufs.type;
+	doioctl(fd, VIDIOC_G_FMT, &fmt);
+
+	is_compressed = is_compressed_format(fmt.fmt.pix.pixelformat);
+
 	if (file_out) {
 		if (!strcmp(file_out, "-"))
 			fin = stdin;
@@ -765,9 +848,9 @@ static void streaming_set_out(int fd)
 				return;
 			}
 		}
-		r = do_handle_out(fd, &reqbufs, is_mplane, num_planes,
-				   buffers, buffer_lengths, fin,
-				   count, last, tv_last);
+		r = do_handle_out(fd, &reqbufs, is_compressed, is_mplane,
+				  num_planes, buffers, buffer_lengths,
+				  fin, count, last, tv_last);
 		if (r == -1)
 			break;
 
@@ -795,6 +878,9 @@ enum stream_type {
 
 static void streaming_set_m2m(int fd)
 {
+	struct v4l2_format fmt;
+	bool is_compressed;
+
 	int fd_flags = fcntl(fd, F_GETFL);
 	bool use_poll = options[OptStreamPoll];
 
@@ -864,6 +950,12 @@ static void streaming_set_m2m(int fd)
 			     is_mmap, buffers_out, buffer_lengths_out,
 			     file[OUT]);
 
+	memset(&fmt, 0, sizeof(fmt));
+	fmt.type = reqbufs[OUT].type;
+	doioctl(fd, VIDIOC_G_FMT, &fmt);
+
+	is_compressed = is_compressed_format(fmt.fmt.pix.pixelformat);
+
 	if (doioctl(fd, VIDIOC_STREAMON, &type[CAP]) ||
 	    doioctl(fd, VIDIOC_STREAMON, &type[OUT]))
 		return;
@@ -927,9 +1019,9 @@ static void streaming_set_m2m(int fd)
 		}
 
 		if (wr_fds && FD_ISSET(fd, wr_fds)) {
-			r  = do_handle_out(fd, &reqbufs[OUT], is_mplane, num_planes[OUT],
-					   buffers_out, buffer_lengths_out, file[OUT],
-					   count[OUT], last[OUT], tv_last[OUT]);
+			r  = do_handle_out(fd, &reqbufs[OUT], is_compressed, is_mplane,
+					   num_planes[OUT], buffers_out, buffer_lengths_out,
+					   file[OUT], count[OUT], last[OUT], tv_last[OUT]);
 			if (r < 0)  {
 				wr_fds = NULL;
 
-- 
1.8.1.5

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux