diff mbox series

[v4l-utils,v5,2/3] v4l2-ctl: Add functions and variables to support fwht stateless decoder

Message ID 20190227070757.25092-3-dafna3@gmail.com (mailing list archive)
State New, archived
Headers show
Series stateless decoder implementation | expand

Commit Message

Dafna Hirschfeld Feb. 27, 2019, 7:07 a.m. UTC
Add the variable 'last_fwht_bf_ts' and the array 'fwht_reqs' to
allow the fwht stateless decoder to maintain the requests.

Signed-off-by: Dafna Hirschfeld <dafna3@gmail.com>
---
 utils/v4l2-ctl/v4l2-ctl-streaming.cpp | 129 ++++++++++++++++++++++++++
 1 file changed, 129 insertions(+)

Comments

Hans Verkuil March 1, 2019, 8:47 a.m. UTC | #1
On 2/27/19 8:07 AM, Dafna Hirschfeld wrote:
> Add the variable 'last_fwht_bf_ts' and the array 'fwht_reqs' to
> allow the fwht stateless decoder to maintain the requests.
> 
> Signed-off-by: Dafna Hirschfeld <dafna3@gmail.com>
> ---
>  utils/v4l2-ctl/v4l2-ctl-streaming.cpp | 129 ++++++++++++++++++++++++++
>  1 file changed, 129 insertions(+)
> 
> diff --git a/utils/v4l2-ctl/v4l2-ctl-streaming.cpp b/utils/v4l2-ctl/v4l2-ctl-streaming.cpp
> index adfa6796..dd0eeef6 100644
> --- a/utils/v4l2-ctl/v4l2-ctl-streaming.cpp
> +++ b/utils/v4l2-ctl/v4l2-ctl-streaming.cpp
> @@ -17,9 +17,12 @@
>  #include <sys/mman.h>
>  #include <dirent.h>
>  #include <math.h>
> +#include <linux/media.h>
>  
>  #include "v4l2-ctl.h"
>  #include "v4l-stream.h"
> +#include <media-info.h>
> +#include <fwht-ctrls.h>
>  
>  extern "C" {
>  #include "v4l2-tpg.h"
> @@ -80,6 +83,16 @@ static bool support_cap_compose;
>  static bool support_out_crop;
>  static bool in_source_change_event;
>  
> +static __u64 last_fwht_bf_ts;
> +
> +struct request_fwht {
> +	int fd;
> +	__u64 ts;
> +	struct v4l2_ctrl_fwht_params params;
> +};
> +
> +static request_fwht fwht_reqs[VIDEO_MAX_FRAME];
> +
>  #define TS_WINDOW 241
>  #define FILE_HDR_ID			v4l2_fourcc('V', 'h', 'd', 'r')
>  
> @@ -420,6 +433,12 @@ static int get_out_crop_rect(cv4l_fd &fd)
>  	return 0;
>  }
>  
> +static __u64 get_ns_timestamp(cv4l_buffer &buf)
> +{
> +	const struct timeval tv = buf.g_timestamp();
> +	return v4l2_timeval_to_ns(&tv);
> +}
> +
>  static void set_time_stamp(cv4l_buffer &buf)
>  {
>  	if ((buf.g_flags() & V4L2_BUF_FLAG_TIMESTAMP_MASK) != V4L2_BUF_FLAG_TIMESTAMP_COPY)
> @@ -749,6 +768,116 @@ void streaming_cmd(int ch, char *optarg)
>  	}
>  }
>  
> +/*
> + * Assume that the fwht stream is valid and that each
> + * frame starts right after the previous one.
> + */
> +static void read_fwht_frame(cv4l_fmt &fmt, unsigned char *buf,
> +			    FILE *fpointer, unsigned &sz,
> +			    unsigned &len)
> +{
> +	struct fwht_cframe_hdr *h = (struct fwht_cframe_hdr *)buf;
> +
> +	len = sizeof(struct fwht_cframe_hdr);
> +	sz = fread(buf, 1, sizeof(struct fwht_cframe_hdr), fpointer);
> +	if (sz < sizeof(struct fwht_cframe_hdr))
> +		return;
> +
> +	len += ntohl(h->size);
> +	sz += fread(buf + sz, 1, ntohl(h->size), fpointer);
> +}
> +
> +static void set_fwht_stateless_params(struct v4l2_ctrl_fwht_params &fwht_params,
> +				      const struct fwht_cframe_hdr *hdr,
> +				      __u64 last_bf_ts)
> +{
> +	fwht_params.backward_ref_ts = last_bf_ts;
> +	fwht_params.version = ntohl(hdr->version);
> +	fwht_params.width = ntohl(hdr->width);
> +	fwht_params.height = ntohl(hdr->height);
> +	fwht_params.flags = ntohl(hdr->flags);
> +	fwht_params.colorspace = ntohl(hdr->colorspace);
> +	fwht_params.xfer_func = ntohl(hdr->xfer_func);
> +	fwht_params.ycbcr_enc = ntohl(hdr->ycbcr_enc);
> +	fwht_params.quantization = ntohl(hdr->quantization);
> +
> +	if (!last_bf_ts)
> +		fwht_params.flags |= FWHT_FL_I_FRAME;

This is to force an I frame if there are no previous reference frames,
right? The video won't look good until the next real I frame, but at
least it will display something.

This could use a comment since it is not obvious what happens.

For a utility like v4l2-ctl it is probably not a bad idea to do it like
this since this will ensure that you at least get some video output.

Regards,

	Hans

> +}
> +
> +static int alloc_fwht_req(int media_fd, unsigned index)
> +{
> +	int rc = 0;
> +
> +	rc = ioctl(media_fd, MEDIA_IOC_REQUEST_ALLOC, &fwht_reqs[index]);
> +	if (rc < 0) {
> +		fprintf(stderr, "Unable to allocate media request: %s\n",
> +			strerror(errno));
> +		return rc;
> +	}
> +
> +	return 0;
> +}
> +
> +static void set_fwht_req_by_idx(unsigned idx, struct fwht_cframe_hdr *hdr,
> +				__u64 last_bf_ts, __u64 ts)
> +{
> +	struct v4l2_ctrl_fwht_params fwht_params;
> +
> +	set_fwht_stateless_params(fwht_params, hdr, last_bf_ts);
> +
> +	fwht_reqs[idx].ts = ts;
> +	fwht_reqs[idx].params = fwht_params;
> +}
> +
> +static int get_fwht_req_by_ts(__u64 ts)
> +{
> +	for (int idx = 0; idx < VIDEO_MAX_FRAME; idx++) {
> +		if (fwht_reqs[idx].ts == ts)
> +			return idx;
> +	}
> +	return -1;
> +}
> +
> +static bool set_fwht_req_by_fd(struct fwht_cframe_hdr *hdr,
> +			       int req_fd, __u64 last_bf_ts, __u64 ts)
> +{
> +	struct v4l2_ctrl_fwht_params fwht_params;
> +
> +	set_fwht_stateless_params(fwht_params, hdr, last_bf_ts);
> +
> +	for (int idx = 0; idx < VIDEO_MAX_FRAME; idx++) {
> +		if (fwht_reqs[idx].fd == req_fd) {
> +			fwht_reqs[idx].ts = ts;
> +			fwht_reqs[idx].params = fwht_params;
> +			return true;
> +		}
> +	}
> +	return false;
> +}
> +
> +static int set_fwht_ext_ctrl(cv4l_fd &fd, struct fwht_cframe_hdr *hdr,
> +			     __u64 last_bf_ts, int req_fd)
> +{
> +	v4l2_ext_controls controls;
> +	struct v4l2_ext_control control;
> +	struct v4l2_ctrl_fwht_params fwht_params;
> +
> +	memset(&control, 0, sizeof(control));
> +	memset(&controls, 0, sizeof(controls));
> +
> +	set_fwht_stateless_params(fwht_params, hdr, last_bf_ts);
> +
> +	control.id = V4L2_CID_MPEG_VIDEO_FWHT_PARAMS;
> +	control.ptr = &fwht_params;
> +	control.size = sizeof(fwht_params);
> +	controls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
> +	controls.request_fd = req_fd;
> +	controls.controls = &control;
> +	controls.count = 1;
> +	return fd.s_ext_ctrls(controls);
> +}
> +
>  static void read_write_padded_frame(cv4l_fmt &fmt, unsigned char *buf,
>  				    FILE *fpointer, unsigned &sz,
>  				    unsigned &len, bool is_read)
>
diff mbox series

Patch

diff --git a/utils/v4l2-ctl/v4l2-ctl-streaming.cpp b/utils/v4l2-ctl/v4l2-ctl-streaming.cpp
index adfa6796..dd0eeef6 100644
--- a/utils/v4l2-ctl/v4l2-ctl-streaming.cpp
+++ b/utils/v4l2-ctl/v4l2-ctl-streaming.cpp
@@ -17,9 +17,12 @@ 
 #include <sys/mman.h>
 #include <dirent.h>
 #include <math.h>
+#include <linux/media.h>
 
 #include "v4l2-ctl.h"
 #include "v4l-stream.h"
+#include <media-info.h>
+#include <fwht-ctrls.h>
 
 extern "C" {
 #include "v4l2-tpg.h"
@@ -80,6 +83,16 @@  static bool support_cap_compose;
 static bool support_out_crop;
 static bool in_source_change_event;
 
+static __u64 last_fwht_bf_ts;
+
+struct request_fwht {
+	int fd;
+	__u64 ts;
+	struct v4l2_ctrl_fwht_params params;
+};
+
+static request_fwht fwht_reqs[VIDEO_MAX_FRAME];
+
 #define TS_WINDOW 241
 #define FILE_HDR_ID			v4l2_fourcc('V', 'h', 'd', 'r')
 
@@ -420,6 +433,12 @@  static int get_out_crop_rect(cv4l_fd &fd)
 	return 0;
 }
 
+static __u64 get_ns_timestamp(cv4l_buffer &buf)
+{
+	const struct timeval tv = buf.g_timestamp();
+	return v4l2_timeval_to_ns(&tv);
+}
+
 static void set_time_stamp(cv4l_buffer &buf)
 {
 	if ((buf.g_flags() & V4L2_BUF_FLAG_TIMESTAMP_MASK) != V4L2_BUF_FLAG_TIMESTAMP_COPY)
@@ -749,6 +768,116 @@  void streaming_cmd(int ch, char *optarg)
 	}
 }
 
+/*
+ * Assume that the fwht stream is valid and that each
+ * frame starts right after the previous one.
+ */
+static void read_fwht_frame(cv4l_fmt &fmt, unsigned char *buf,
+			    FILE *fpointer, unsigned &sz,
+			    unsigned &len)
+{
+	struct fwht_cframe_hdr *h = (struct fwht_cframe_hdr *)buf;
+
+	len = sizeof(struct fwht_cframe_hdr);
+	sz = fread(buf, 1, sizeof(struct fwht_cframe_hdr), fpointer);
+	if (sz < sizeof(struct fwht_cframe_hdr))
+		return;
+
+	len += ntohl(h->size);
+	sz += fread(buf + sz, 1, ntohl(h->size), fpointer);
+}
+
+static void set_fwht_stateless_params(struct v4l2_ctrl_fwht_params &fwht_params,
+				      const struct fwht_cframe_hdr *hdr,
+				      __u64 last_bf_ts)
+{
+	fwht_params.backward_ref_ts = last_bf_ts;
+	fwht_params.version = ntohl(hdr->version);
+	fwht_params.width = ntohl(hdr->width);
+	fwht_params.height = ntohl(hdr->height);
+	fwht_params.flags = ntohl(hdr->flags);
+	fwht_params.colorspace = ntohl(hdr->colorspace);
+	fwht_params.xfer_func = ntohl(hdr->xfer_func);
+	fwht_params.ycbcr_enc = ntohl(hdr->ycbcr_enc);
+	fwht_params.quantization = ntohl(hdr->quantization);
+
+	if (!last_bf_ts)
+		fwht_params.flags |= FWHT_FL_I_FRAME;
+}
+
+static int alloc_fwht_req(int media_fd, unsigned index)
+{
+	int rc = 0;
+
+	rc = ioctl(media_fd, MEDIA_IOC_REQUEST_ALLOC, &fwht_reqs[index]);
+	if (rc < 0) {
+		fprintf(stderr, "Unable to allocate media request: %s\n",
+			strerror(errno));
+		return rc;
+	}
+
+	return 0;
+}
+
+static void set_fwht_req_by_idx(unsigned idx, struct fwht_cframe_hdr *hdr,
+				__u64 last_bf_ts, __u64 ts)
+{
+	struct v4l2_ctrl_fwht_params fwht_params;
+
+	set_fwht_stateless_params(fwht_params, hdr, last_bf_ts);
+
+	fwht_reqs[idx].ts = ts;
+	fwht_reqs[idx].params = fwht_params;
+}
+
+static int get_fwht_req_by_ts(__u64 ts)
+{
+	for (int idx = 0; idx < VIDEO_MAX_FRAME; idx++) {
+		if (fwht_reqs[idx].ts == ts)
+			return idx;
+	}
+	return -1;
+}
+
+static bool set_fwht_req_by_fd(struct fwht_cframe_hdr *hdr,
+			       int req_fd, __u64 last_bf_ts, __u64 ts)
+{
+	struct v4l2_ctrl_fwht_params fwht_params;
+
+	set_fwht_stateless_params(fwht_params, hdr, last_bf_ts);
+
+	for (int idx = 0; idx < VIDEO_MAX_FRAME; idx++) {
+		if (fwht_reqs[idx].fd == req_fd) {
+			fwht_reqs[idx].ts = ts;
+			fwht_reqs[idx].params = fwht_params;
+			return true;
+		}
+	}
+	return false;
+}
+
+static int set_fwht_ext_ctrl(cv4l_fd &fd, struct fwht_cframe_hdr *hdr,
+			     __u64 last_bf_ts, int req_fd)
+{
+	v4l2_ext_controls controls;
+	struct v4l2_ext_control control;
+	struct v4l2_ctrl_fwht_params fwht_params;
+
+	memset(&control, 0, sizeof(control));
+	memset(&controls, 0, sizeof(controls));
+
+	set_fwht_stateless_params(fwht_params, hdr, last_bf_ts);
+
+	control.id = V4L2_CID_MPEG_VIDEO_FWHT_PARAMS;
+	control.ptr = &fwht_params;
+	control.size = sizeof(fwht_params);
+	controls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
+	controls.request_fd = req_fd;
+	controls.controls = &control;
+	controls.count = 1;
+	return fd.s_ext_ctrls(controls);
+}
+
 static void read_write_padded_frame(cv4l_fmt &fmt, unsigned char *buf,
 				    FILE *fpointer, unsigned &sz,
 				    unsigned &len, bool is_read)