media: allegro: adjust channel after format change

A format change (i.e. the frame size or the codec) has multiple effects
on a channel:

- The available controls

- The limits of the available controls

- The default encoding options

To avoid scattering the changes all over the driver, add a new function
that goes over the channel and does all required adjustments.

Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
Michael Tretter 2020-12-03 12:00:53 +01:00 committed by Mauro Carvalho Chehab
parent 8e64f00846
commit d2a1b58fd2
1 changed files with 52 additions and 17 deletions

View File

@ -1963,7 +1963,6 @@ static int allegro_create_channel(struct allegro_channel *channel)
{ {
struct allegro_dev *dev = channel->dev; struct allegro_dev *dev = channel->dev;
unsigned long timeout; unsigned long timeout;
enum v4l2_mpeg_video_h264_level min_level;
if (channel_exists(channel)) { if (channel_exists(channel)) {
v4l2_warn(&dev->v4l2_dev, v4l2_warn(&dev->v4l2_dev,
@ -1986,16 +1985,6 @@ static int allegro_create_channel(struct allegro_channel *channel)
DIV_ROUND_UP(channel->framerate.numerator, DIV_ROUND_UP(channel->framerate.numerator,
channel->framerate.denominator)); channel->framerate.denominator));
min_level = select_minimum_h264_level(channel->width, channel->height);
if (channel->level < min_level) {
v4l2_warn(&dev->v4l2_dev,
"user %d: selected Level %s too low: increasing to Level %s\n",
channel->user_id,
v4l2_ctrl_get_menu(V4L2_CID_MPEG_VIDEO_H264_LEVEL)[channel->level],
v4l2_ctrl_get_menu(V4L2_CID_MPEG_VIDEO_H264_LEVEL)[min_level]);
channel->level = min_level;
}
v4l2_ctrl_grab(channel->mpeg_video_h264_profile, true); v4l2_ctrl_grab(channel->mpeg_video_h264_profile, true);
v4l2_ctrl_grab(channel->mpeg_video_h264_level, true); v4l2_ctrl_grab(channel->mpeg_video_h264_level, true);
v4l2_ctrl_grab(channel->mpeg_video_h264_i_frame_qp, true); v4l2_ctrl_grab(channel->mpeg_video_h264_i_frame_qp, true);
@ -2031,6 +2020,53 @@ err:
return channel->error; return channel->error;
} }
/**
* allegro_channel_adjust() - Adjust channel parameters to current format
* @channel: the channel to adjust
*
* Various parameters of a channel and their limits depend on the currently
* set format. Adjust the parameters after a format change in one go.
*/
static void allegro_channel_adjust(struct allegro_channel *channel)
{
struct allegro_dev *dev = channel->dev;
struct v4l2_ctrl *ctrl;
s64 min;
s64 max;
channel->sizeimage_encoded =
estimate_stream_size(channel->width, channel->height);
ctrl = channel->mpeg_video_h264_level;
min = select_minimum_h264_level(channel->width, channel->height);
if (ctrl->minimum > min)
v4l2_dbg(1, debug, &dev->v4l2_dev,
"%s.minimum: %lld -> %lld\n",
v4l2_ctrl_get_name(ctrl->id), ctrl->minimum, min);
v4l2_ctrl_lock(ctrl);
__v4l2_ctrl_modify_range(ctrl, min, ctrl->maximum,
ctrl->step, ctrl->default_value);
v4l2_ctrl_unlock(ctrl);
channel->level = v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_level);
ctrl = channel->mpeg_video_bitrate;
max = maximum_bitrate(v4l2_ctrl_g_ctrl(channel->mpeg_video_h264_level));
if (ctrl->maximum < max)
v4l2_dbg(1, debug, &dev->v4l2_dev,
"%s: maximum: %lld -> %lld\n",
v4l2_ctrl_get_name(ctrl->id), ctrl->maximum, max);
v4l2_ctrl_lock(ctrl);
__v4l2_ctrl_modify_range(ctrl, ctrl->minimum, max,
ctrl->step, ctrl->default_value);
v4l2_ctrl_unlock(ctrl);
ctrl = channel->mpeg_video_bitrate_peak;
v4l2_ctrl_lock(ctrl);
__v4l2_ctrl_modify_range(ctrl, ctrl->minimum, max,
ctrl->step, ctrl->default_value);
v4l2_ctrl_unlock(ctrl);
}
static void allegro_set_default_params(struct allegro_channel *channel) static void allegro_set_default_params(struct allegro_channel *channel)
{ {
channel->width = ALLEGRO_WIDTH_DEFAULT; channel->width = ALLEGRO_WIDTH_DEFAULT;
@ -2050,8 +2086,6 @@ static void allegro_set_default_params(struct allegro_channel *channel)
channel->profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE; channel->profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
channel->level = channel->level =
select_minimum_h264_level(channel->width, channel->height); select_minimum_h264_level(channel->width, channel->height);
channel->sizeimage_encoded =
estimate_stream_size(channel->width, channel->height);
channel->bitrate = maximum_bitrate(channel->level); channel->bitrate = maximum_bitrate(channel->level);
channel->bitrate_peak = maximum_bitrate(channel->level); channel->bitrate_peak = maximum_bitrate(channel->level);
@ -2459,6 +2493,8 @@ static int allegro_open(struct file *file)
file->private_data = &channel->fh; file->private_data = &channel->fh;
v4l2_fh_add(&channel->fh); v4l2_fh_add(&channel->fh);
allegro_channel_adjust(channel);
return 0; return 0;
error: error:
@ -2577,6 +2613,8 @@ static int allegro_s_fmt_vid_cap(struct file *file, void *fh,
channel->codec = f->fmt.pix.pixelformat; channel->codec = f->fmt.pix.pixelformat;
allegro_channel_adjust(channel);
return 0; return 0;
} }
@ -2647,10 +2685,7 @@ static int allegro_s_fmt_vid_out(struct file *file, void *fh,
channel->quantization = f->fmt.pix.quantization; channel->quantization = f->fmt.pix.quantization;
channel->xfer_func = f->fmt.pix.xfer_func; channel->xfer_func = f->fmt.pix.xfer_func;
channel->level = allegro_channel_adjust(channel);
select_minimum_h264_level(channel->width, channel->height);
channel->sizeimage_encoded =
estimate_stream_size(channel->width, channel->height);
return 0; return 0;
} }