diff mbox series

[v4] venus: venc: Fix enum frameintervals

Message ID 20191003101038.13732-1-stanimir.varbanov@linaro.org (mailing list archive)
State New, archived
Headers show
Series [v4] venus: venc: Fix enum frameintervals | expand

Commit Message

Stanimir Varbanov Oct. 3, 2019, 10:10 a.m. UTC
This fixes an issue when setting the encoder framerate because of
missing precision. Now the frameinterval type is changed to
TYPE_CONTINUOUS and step = 1. Also the math is changed when
framerate property is called - the firmware side expects the
framerate in Q16 values.

Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
---

Changes since v3:
Keep min/max numerator one, and divide frate(max/min) to frame
factor (returned framerate max/min capabilities are in range
1 to 120fps but in Q16 i.e. 65536 to 7864320).

 drivers/media/platform/qcom/venus/venc.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

Comments

Stanimir Varbanov Oct. 3, 2019, 10:15 a.m. UTC | #1
I have tested this on db410c with following gst pipeline:

gst-launch-1.0 -v videotestsrc !
video/x-raw,format=NV12,width=1280,height=960,framerate=24/1 !
v4l2h264enc
extra-controls="controls,h264_profile=4,h264_level="5",video_bitrate=10000000;"
! filesink location=gstenc.h264

Loic, could you give it a try on db820c too?

Here is the info on the bug which I try to fix with current patch:

https://bugs.96boards.org/show_bug.cgi?id=513

On 10/3/19 1:10 PM, Stanimir Varbanov wrote:
> This fixes an issue when setting the encoder framerate because of
> missing precision. Now the frameinterval type is changed to
> TYPE_CONTINUOUS and step = 1. Also the math is changed when
> framerate property is called - the firmware side expects the
> framerate in Q16 values.
> 
> Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
> ---
> 
> Changes since v3:
> Keep min/max numerator one, and divide frate(max/min) to frame
> factor (returned framerate max/min capabilities are in range
> 1 to 120fps but in Q16 i.e. 65536 to 7864320).
> 
>  drivers/media/platform/qcom/venus/venc.c | 17 ++++++++++++-----
>  1 file changed, 12 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
> index 1b7fb2d5887c..133ff7eceb83 100644
> --- a/drivers/media/platform/qcom/venus/venc.c
> +++ b/drivers/media/platform/qcom/venus/venc.c
> @@ -22,6 +22,7 @@
>  #include "venc.h"
>  
>  #define NUM_B_FRAMES_MAX	4
> +#define FRAMERATE_FACTOR	BIT(16)
>  
>  /*
>   * Three resons to keep MPLANE formats (despite that the number of planes
> @@ -576,7 +577,7 @@ static int venc_enum_frameintervals(struct file *file, void *fh,
>  	struct venus_inst *inst = to_inst(file);
>  	const struct venus_format *fmt;
>  
> -	fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
> +	fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
>  
>  	fmt = find_format(inst, fival->pixel_format,
>  			  V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
> @@ -600,11 +601,11 @@ static int venc_enum_frameintervals(struct file *file, void *fh,
>  		return -EINVAL;
>  
>  	fival->stepwise.min.numerator = 1;
> -	fival->stepwise.min.denominator = frate_max(inst);
> +	fival->stepwise.min.denominator = frate_max(inst) / FRAMERATE_FACTOR;
>  	fival->stepwise.max.numerator = 1;
> -	fival->stepwise.max.denominator = frate_min(inst);
> +	fival->stepwise.max.denominator = frate_min(inst) / FRAMERATE_FACTOR;
>  	fival->stepwise.step.numerator = 1;
> -	fival->stepwise.step.denominator = frate_max(inst);
> +	fival->stepwise.step.denominator = 1;
>  
>  	return 0;
>  }
> @@ -649,6 +650,7 @@ static int venc_set_properties(struct venus_inst *inst)
>  	struct hfi_quantization quant;
>  	struct hfi_quantization_range quant_range;
>  	u32 ptype, rate_control, bitrate, profile = 0, level = 0;
> +	u64 framerate;
>  	int ret;
>  
>  	ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2);
> @@ -659,9 +661,14 @@ static int venc_set_properties(struct venus_inst *inst)
>  	if (ret)
>  		return ret;
>  
> +	framerate = inst->timeperframe.denominator * FRAMERATE_FACTOR;
> +	/* next line is to round up */
> +	framerate += inst->timeperframe.numerator - 1;
> +	do_div(framerate, inst->timeperframe.numerator);
> +
>  	ptype = HFI_PROPERTY_CONFIG_FRAME_RATE;
>  	frate.buffer_type = HFI_BUFFER_OUTPUT;
> -	frate.framerate = inst->fps * (1 << 16);
> +	frate.framerate = framerate;
>  
>  	ret = hfi_session_set_property(inst, ptype, &frate);
>  	if (ret)
>
Mauro Carvalho Chehab Oct. 4, 2019, 11:48 a.m. UTC | #2
Em Thu,  3 Oct 2019 13:10:38 +0300
Stanimir Varbanov <stanimir.varbanov@linaro.org> escreveu:

> This fixes an issue when setting the encoder framerate because of
> missing precision. Now the frameinterval type is changed to
> TYPE_CONTINUOUS and step = 1. Also the math is changed when
> framerate property is called - the firmware side expects the
> framerate in Q16 values.
> 
> Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>

Didn't test the patch, but just reviewing the code, this version
looks OK on my eyes.

> ---
> 
> Changes since v3:
> Keep min/max numerator one, and divide frate(max/min) to frame
> factor (returned framerate max/min capabilities are in range
> 1 to 120fps but in Q16 i.e. 65536 to 7864320).
> 
>  drivers/media/platform/qcom/venus/venc.c | 17 ++++++++++++-----
>  1 file changed, 12 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
> index 1b7fb2d5887c..133ff7eceb83 100644
> --- a/drivers/media/platform/qcom/venus/venc.c
> +++ b/drivers/media/platform/qcom/venus/venc.c
> @@ -22,6 +22,7 @@
>  #include "venc.h"
>  
>  #define NUM_B_FRAMES_MAX	4
> +#define FRAMERATE_FACTOR	BIT(16)
>  
>  /*
>   * Three resons to keep MPLANE formats (despite that the number of planes
> @@ -576,7 +577,7 @@ static int venc_enum_frameintervals(struct file *file, void *fh,
>  	struct venus_inst *inst = to_inst(file);
>  	const struct venus_format *fmt;
>  
> -	fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
> +	fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
>  
>  	fmt = find_format(inst, fival->pixel_format,
>  			  V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
> @@ -600,11 +601,11 @@ static int venc_enum_frameintervals(struct file *file, void *fh,
>  		return -EINVAL;
>  
>  	fival->stepwise.min.numerator = 1;
> -	fival->stepwise.min.denominator = frate_max(inst);
> +	fival->stepwise.min.denominator = frate_max(inst) / FRAMERATE_FACTOR;
>  	fival->stepwise.max.numerator = 1;
> -	fival->stepwise.max.denominator = frate_min(inst);
> +	fival->stepwise.max.denominator = frate_min(inst) / FRAMERATE_FACTOR;
>  	fival->stepwise.step.numerator = 1;
> -	fival->stepwise.step.denominator = frate_max(inst);
> +	fival->stepwise.step.denominator = 1;
>  
>  	return 0;
>  }
> @@ -649,6 +650,7 @@ static int venc_set_properties(struct venus_inst *inst)
>  	struct hfi_quantization quant;
>  	struct hfi_quantization_range quant_range;
>  	u32 ptype, rate_control, bitrate, profile = 0, level = 0;
> +	u64 framerate;
>  	int ret;
>  
>  	ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2);
> @@ -659,9 +661,14 @@ static int venc_set_properties(struct venus_inst *inst)
>  	if (ret)
>  		return ret;
>  
> +	framerate = inst->timeperframe.denominator * FRAMERATE_FACTOR;
> +	/* next line is to round up */
> +	framerate += inst->timeperframe.numerator - 1;
> +	do_div(framerate, inst->timeperframe.numerator);
> +
>  	ptype = HFI_PROPERTY_CONFIG_FRAME_RATE;
>  	frate.buffer_type = HFI_BUFFER_OUTPUT;
> -	frate.framerate = inst->fps * (1 << 16);
> +	frate.framerate = framerate;
>  
>  	ret = hfi_session_set_property(inst, ptype, &frate);
>  	if (ret)



Thanks,
Mauro
Loic Poulain Oct. 17, 2019, 3:08 p.m. UTC | #3
Hi Stanimir,

On Thu, 3 Oct 2019 at 12:15, Stanimir Varbanov
<stanimir.varbanov@linaro.org> wrote:
>
> I have tested this on db410c with following gst pipeline:
>
> gst-launch-1.0 -v videotestsrc !
> video/x-raw,format=NV12,width=1280,height=960,framerate=24/1 !
> v4l2h264enc
> extra-controls="controls,h264_profile=4,h264_level="5",video_bitrate=10000000;"
> ! filesink location=gstenc.h264
>
> Loic, could you give it a try on db820c too?
>
> Here is the info on the bug which I try to fix with current patch:
>
> https://bugs.96boards.org/show_bug.cgi?id=513
>
> On 10/3/19 1:10 PM, Stanimir Varbanov wrote:
> > This fixes an issue when setting the encoder framerate because of
> > missing precision. Now the frameinterval type is changed to
> > TYPE_CONTINUOUS and step = 1. Also the math is changed when
> > framerate property is called - the firmware side expects the
> > framerate in Q16 values.
> >
> > Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
> > ---
> >
> > Changes since v3:
> > Keep min/max numerator one, and divide frate(max/min) to frame
> > factor (returned framerate max/min capabilities are in range
> > 1 to 120fps but in Q16 i.e. 65536 to 7864320).
> >
> >  drivers/media/platform/qcom/venus/venc.c | 17 ++++++++++++-----
> >  1 file changed, 12 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
> > index 1b7fb2d5887c..133ff7eceb83 100644
> > --- a/drivers/media/platform/qcom/venus/venc.c
> > +++ b/drivers/media/platform/qcom/venus/venc.c
> > @@ -22,6 +22,7 @@
> >  #include "venc.h"
> >
> >  #define NUM_B_FRAMES_MAX     4
> > +#define FRAMERATE_FACTOR     BIT(16)
> >
> >  /*
> >   * Three resons to keep MPLANE formats (despite that the number of planes
> > @@ -576,7 +577,7 @@ static int venc_enum_frameintervals(struct file *file, void *fh,
> >       struct venus_inst *inst = to_inst(file);
> >       const struct venus_format *fmt;
> >
> > -     fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
> > +     fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
> >
> >       fmt = find_format(inst, fival->pixel_format,
> >                         V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
> > @@ -600,11 +601,11 @@ static int venc_enum_frameintervals(struct file *file, void *fh,
> >               return -EINVAL;
> >
> >       fival->stepwise.min.numerator = 1;
> > -     fival->stepwise.min.denominator = frate_max(inst);
> > +     fival->stepwise.min.denominator = frate_max(inst) / FRAMERATE_FACTOR;

On 820c frate_max() returns 120 set denominator to 0, and causes
gstreamer failure.

Regards,
Loic
Stanimir Varbanov Oct. 17, 2019, 3:47 p.m. UTC | #4
Hi Loic,

On 10/17/19 6:08 PM, Loic Poulain wrote:
> Hi Stanimir,
> 
> On Thu, 3 Oct 2019 at 12:15, Stanimir Varbanov
> <stanimir.varbanov@linaro.org> wrote:
>>
>> I have tested this on db410c with following gst pipeline:
>>
>> gst-launch-1.0 -v videotestsrc !
>> video/x-raw,format=NV12,width=1280,height=960,framerate=24/1 !
>> v4l2h264enc
>> extra-controls="controls,h264_profile=4,h264_level="5",video_bitrate=10000000;"
>> ! filesink location=gstenc.h264
>>
>> Loic, could you give it a try on db820c too?
>>
>> Here is the info on the bug which I try to fix with current patch:
>>
>> https://bugs.96boards.org/show_bug.cgi?id=513
>>
>> On 10/3/19 1:10 PM, Stanimir Varbanov wrote:
>>> This fixes an issue when setting the encoder framerate because of
>>> missing precision. Now the frameinterval type is changed to
>>> TYPE_CONTINUOUS and step = 1. Also the math is changed when
>>> framerate property is called - the firmware side expects the
>>> framerate in Q16 values.
>>>
>>> Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
>>> ---
>>>
>>> Changes since v3:
>>> Keep min/max numerator one, and divide frate(max/min) to frame
>>> factor (returned framerate max/min capabilities are in range
>>> 1 to 120fps but in Q16 i.e. 65536 to 7864320).
>>>
>>>  drivers/media/platform/qcom/venus/venc.c | 17 ++++++++++++-----
>>>  1 file changed, 12 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
>>> index 1b7fb2d5887c..133ff7eceb83 100644
>>> --- a/drivers/media/platform/qcom/venus/venc.c
>>> +++ b/drivers/media/platform/qcom/venus/venc.c
>>> @@ -22,6 +22,7 @@
>>>  #include "venc.h"
>>>
>>>  #define NUM_B_FRAMES_MAX     4
>>> +#define FRAMERATE_FACTOR     BIT(16)
>>>
>>>  /*
>>>   * Three resons to keep MPLANE formats (despite that the number of planes
>>> @@ -576,7 +577,7 @@ static int venc_enum_frameintervals(struct file *file, void *fh,
>>>       struct venus_inst *inst = to_inst(file);
>>>       const struct venus_format *fmt;
>>>
>>> -     fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
>>> +     fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
>>>
>>>       fmt = find_format(inst, fival->pixel_format,
>>>                         V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
>>> @@ -600,11 +601,11 @@ static int venc_enum_frameintervals(struct file *file, void *fh,
>>>               return -EINVAL;
>>>
>>>       fival->stepwise.min.numerator = 1;
>>> -     fival->stepwise.min.denominator = frate_max(inst);
>>> +     fival->stepwise.min.denominator = frate_max(inst) / FRAMERATE_FACTOR;
> 
> On 820c frate_max() returns 120 set denominator to 0, and causes
> gstreamer failure.

OK, thanks!

We have two options
- unify frate_min/max() to return in Q16 depending on the hfi version
- or move frame_factor in frate_min/max() and return the framerate (1..120)
Loic Poulain Oct. 17, 2019, 5:50 p.m. UTC | #5
Hi Stanimir,

On Thu, 17 Oct 2019 at 17:47, Stanimir Varbanov
<stanimir.varbanov@linaro.org> wrote:
>
> Hi Loic,
>
> On 10/17/19 6:08 PM, Loic Poulain wrote:
> > Hi Stanimir,
> >
> > On Thu, 3 Oct 2019 at 12:15, Stanimir Varbanov
> > <stanimir.varbanov@linaro.org> wrote:
> >>
> >> I have tested this on db410c with following gst pipeline:
> >>
> >> gst-launch-1.0 -v videotestsrc !
> >> video/x-raw,format=NV12,width=1280,height=960,framerate=24/1 !
> >> v4l2h264enc
> >> extra-controls="controls,h264_profile=4,h264_level="5",video_bitrate=10000000;"
> >> ! filesink location=gstenc.h264
> >>
> >> Loic, could you give it a try on db820c too?
> >>
> >> Here is the info on the bug which I try to fix with current patch:
> >>
> >> https://bugs.96boards.org/show_bug.cgi?id=513
> >>
> >> On 10/3/19 1:10 PM, Stanimir Varbanov wrote:
> >>> This fixes an issue when setting the encoder framerate because of
> >>> missing precision. Now the frameinterval type is changed to
> >>> TYPE_CONTINUOUS and step = 1. Also the math is changed when
> >>> framerate property is called - the firmware side expects the
> >>> framerate in Q16 values.
> >>>
> >>> Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
> >>> ---
> >>>
> >>> Changes since v3:
> >>> Keep min/max numerator one, and divide frate(max/min) to frame
> >>> factor (returned framerate max/min capabilities are in range
> >>> 1 to 120fps but in Q16 i.e. 65536 to 7864320).
> >>>
> >>>  drivers/media/platform/qcom/venus/venc.c | 17 ++++++++++++-----
> >>>  1 file changed, 12 insertions(+), 5 deletions(-)
> >>>
> >>> diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
> >>> index 1b7fb2d5887c..133ff7eceb83 100644
> >>> --- a/drivers/media/platform/qcom/venus/venc.c
> >>> +++ b/drivers/media/platform/qcom/venus/venc.c
> >>> @@ -22,6 +22,7 @@
> >>>  #include "venc.h"
> >>>
> >>>  #define NUM_B_FRAMES_MAX     4
> >>> +#define FRAMERATE_FACTOR     BIT(16)
> >>>
> >>>  /*
> >>>   * Three resons to keep MPLANE formats (despite that the number of planes
> >>> @@ -576,7 +577,7 @@ static int venc_enum_frameintervals(struct file *file, void *fh,
> >>>       struct venus_inst *inst = to_inst(file);
> >>>       const struct venus_format *fmt;
> >>>
> >>> -     fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
> >>> +     fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
> >>>
> >>>       fmt = find_format(inst, fival->pixel_format,
> >>>                         V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
> >>> @@ -600,11 +601,11 @@ static int venc_enum_frameintervals(struct file *file, void *fh,
> >>>               return -EINVAL;
> >>>
> >>>       fival->stepwise.min.numerator = 1;
> >>> -     fival->stepwise.min.denominator = frate_max(inst);
> >>> +     fival->stepwise.min.denominator = frate_max(inst) / FRAMERATE_FACTOR;
> >
> > On 820c frate_max() returns 120 set denominator to 0, and causes
> > gstreamer failure.
>
> OK, thanks!
>
> We have two options
> - unify frate_min/max() to return in Q16 depending on the hfi version
> - or move frame_factor in frate_min/max() and return the framerate (1..120)

No strong preference...

Regards,
Loic
diff mbox series

Patch

diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
index 1b7fb2d5887c..133ff7eceb83 100644
--- a/drivers/media/platform/qcom/venus/venc.c
+++ b/drivers/media/platform/qcom/venus/venc.c
@@ -22,6 +22,7 @@ 
 #include "venc.h"
 
 #define NUM_B_FRAMES_MAX	4
+#define FRAMERATE_FACTOR	BIT(16)
 
 /*
  * Three resons to keep MPLANE formats (despite that the number of planes
@@ -576,7 +577,7 @@  static int venc_enum_frameintervals(struct file *file, void *fh,
 	struct venus_inst *inst = to_inst(file);
 	const struct venus_format *fmt;
 
-	fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
+	fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
 
 	fmt = find_format(inst, fival->pixel_format,
 			  V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
@@ -600,11 +601,11 @@  static int venc_enum_frameintervals(struct file *file, void *fh,
 		return -EINVAL;
 
 	fival->stepwise.min.numerator = 1;
-	fival->stepwise.min.denominator = frate_max(inst);
+	fival->stepwise.min.denominator = frate_max(inst) / FRAMERATE_FACTOR;
 	fival->stepwise.max.numerator = 1;
-	fival->stepwise.max.denominator = frate_min(inst);
+	fival->stepwise.max.denominator = frate_min(inst) / FRAMERATE_FACTOR;
 	fival->stepwise.step.numerator = 1;
-	fival->stepwise.step.denominator = frate_max(inst);
+	fival->stepwise.step.denominator = 1;
 
 	return 0;
 }
@@ -649,6 +650,7 @@  static int venc_set_properties(struct venus_inst *inst)
 	struct hfi_quantization quant;
 	struct hfi_quantization_range quant_range;
 	u32 ptype, rate_control, bitrate, profile = 0, level = 0;
+	u64 framerate;
 	int ret;
 
 	ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2);
@@ -659,9 +661,14 @@  static int venc_set_properties(struct venus_inst *inst)
 	if (ret)
 		return ret;
 
+	framerate = inst->timeperframe.denominator * FRAMERATE_FACTOR;
+	/* next line is to round up */
+	framerate += inst->timeperframe.numerator - 1;
+	do_div(framerate, inst->timeperframe.numerator);
+
 	ptype = HFI_PROPERTY_CONFIG_FRAME_RATE;
 	frate.buffer_type = HFI_BUFFER_OUTPUT;
-	frate.framerate = inst->fps * (1 << 16);
+	frate.framerate = framerate;
 
 	ret = hfi_session_set_property(inst, ptype, &frate);
 	if (ret)