Commit 19505719 authored by Dafna Hirschfeld's avatar Dafna Hirschfeld Committed by Mauro Carvalho Chehab

media: vicodec: Add support of greyscale format

Add support for single plane greyscale format V4L2_PIX_FMT_GREY.
Also change the header of the encoded file to include the number
of components.
Signed-off-by: default avatarDafna Hirschfeld <dafna3@gmail.com>
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
[hans.verkuil@cisco.com: fix line-too-long warnings]
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent aec89917
...@@ -753,9 +753,6 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm, ...@@ -753,9 +753,6 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm,
__be16 *rlco = cf->rlc_data; __be16 *rlco = cf->rlc_data;
__be16 *rlco_max; __be16 *rlco_max;
u32 encoding; u32 encoding;
u32 chroma_h = frm->height / frm->height_div;
u32 chroma_w = frm->width / frm->width_div;
unsigned int chroma_size = chroma_h * chroma_w;
rlco_max = rlco + size / 2 - 256; rlco_max = rlco + size / 2 - 256;
encoding = encode_plane(frm->luma, ref_frm->luma, &rlco, rlco_max, cf, encoding = encode_plane(frm->luma, ref_frm->luma, &rlco, rlco_max, cf,
...@@ -764,20 +761,29 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm, ...@@ -764,20 +761,29 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm,
if (encoding & FWHT_FRAME_UNENCODED) if (encoding & FWHT_FRAME_UNENCODED)
encoding |= FWHT_LUMA_UNENCODED; encoding |= FWHT_LUMA_UNENCODED;
encoding &= ~FWHT_FRAME_UNENCODED; encoding &= ~FWHT_FRAME_UNENCODED;
if (frm->components_num >= 3) {
u32 chroma_h = frm->height / frm->height_div;
u32 chroma_w = frm->width / frm->width_div;
unsigned int chroma_size = chroma_h * chroma_w;
rlco_max = rlco + chroma_size / 2 - 256; rlco_max = rlco + chroma_size / 2 - 256;
encoding |= encode_plane(frm->cb, ref_frm->cb, &rlco, rlco_max, cf, encoding |= encode_plane(frm->cb, ref_frm->cb, &rlco, rlco_max,
chroma_h, chroma_w, cf, chroma_h, chroma_w,
frm->chroma_step, is_intra, next_is_intra); frm->chroma_step,
is_intra, next_is_intra);
if (encoding & FWHT_FRAME_UNENCODED) if (encoding & FWHT_FRAME_UNENCODED)
encoding |= FWHT_CB_UNENCODED; encoding |= FWHT_CB_UNENCODED;
encoding &= ~FWHT_FRAME_UNENCODED; encoding &= ~FWHT_FRAME_UNENCODED;
rlco_max = rlco + chroma_size / 2 - 256; rlco_max = rlco + chroma_size / 2 - 256;
encoding |= encode_plane(frm->cr, ref_frm->cr, &rlco, rlco_max, cf, encoding |= encode_plane(frm->cr, ref_frm->cr, &rlco, rlco_max,
chroma_h, chroma_w, cf, chroma_h, chroma_w,
frm->chroma_step, is_intra, next_is_intra); frm->chroma_step,
is_intra, next_is_intra);
if (encoding & FWHT_FRAME_UNENCODED) if (encoding & FWHT_FRAME_UNENCODED)
encoding |= FWHT_CR_UNENCODED; encoding |= FWHT_CR_UNENCODED;
encoding &= ~FWHT_FRAME_UNENCODED; encoding &= ~FWHT_FRAME_UNENCODED;
}
cf->size = (rlco - cf->rlc_data) * sizeof(*rlco); cf->size = (rlco - cf->rlc_data) * sizeof(*rlco);
return encoding; return encoding;
} }
...@@ -836,20 +842,24 @@ static void decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref, ...@@ -836,20 +842,24 @@ static void decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref,
} }
void fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref, void fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref,
u32 hdr_flags) u32 hdr_flags, unsigned int components_num)
{ {
const __be16 *rlco = cf->rlc_data; const __be16 *rlco = cf->rlc_data;
u32 h = cf->height / 2;
u32 w = cf->width / 2;
if (hdr_flags & FWHT_FL_CHROMA_FULL_HEIGHT)
h *= 2;
if (hdr_flags & FWHT_FL_CHROMA_FULL_WIDTH)
w *= 2;
decode_plane(cf, &rlco, ref->luma, cf->height, cf->width, decode_plane(cf, &rlco, ref->luma, cf->height, cf->width,
hdr_flags & FWHT_FL_LUMA_IS_UNCOMPRESSED); hdr_flags & FWHT_FL_LUMA_IS_UNCOMPRESSED);
if (components_num >= 3) {
u32 h = cf->height;
u32 w = cf->width;
if (!(hdr_flags & FWHT_FL_CHROMA_FULL_HEIGHT))
h /= 2;
if (!(hdr_flags & FWHT_FL_CHROMA_FULL_WIDTH))
w /= 2;
decode_plane(cf, &rlco, ref->cb, h, w, decode_plane(cf, &rlco, ref->cb, h, w,
hdr_flags & FWHT_FL_CB_IS_UNCOMPRESSED); hdr_flags & FWHT_FL_CB_IS_UNCOMPRESSED);
decode_plane(cf, &rlco, ref->cr, h, w, decode_plane(cf, &rlco, ref->cr, h, w,
hdr_flags & FWHT_FL_CR_IS_UNCOMPRESSED); hdr_flags & FWHT_FL_CR_IS_UNCOMPRESSED);
}
} }
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
#define FWHT_MAGIC1 0x4f4f4f4f #define FWHT_MAGIC1 0x4f4f4f4f
#define FWHT_MAGIC2 0xffffffff #define FWHT_MAGIC2 0xffffffff
#define FWHT_VERSION 1 #define FWHT_VERSION 2
/* Set if this is an interlaced format */ /* Set if this is an interlaced format */
#define FWHT_FL_IS_INTERLACED BIT(0) #define FWHT_FL_IS_INTERLACED BIT(0)
...@@ -76,6 +76,10 @@ ...@@ -76,6 +76,10 @@
#define FWHT_FL_CHROMA_FULL_HEIGHT BIT(7) #define FWHT_FL_CHROMA_FULL_HEIGHT BIT(7)
#define FWHT_FL_CHROMA_FULL_WIDTH BIT(8) #define FWHT_FL_CHROMA_FULL_WIDTH BIT(8)
/* A 4-values flag - the number of components - 1 */
#define FWHT_FL_COMPONENTS_NUM_MSK GENMASK(17, 16)
#define FWHT_FL_COMPONENTS_NUM_OFFSET 16
struct fwht_cframe_hdr { struct fwht_cframe_hdr {
u32 magic1; u32 magic1;
u32 magic2; u32 magic2;
...@@ -121,6 +125,6 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm, ...@@ -121,6 +125,6 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm,
struct fwht_cframe *cf, struct fwht_cframe *cf,
bool is_intra, bool next_is_intra); bool is_intra, bool next_is_intra);
void fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref, void fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref,
u32 hdr_flags); u32 hdr_flags, unsigned int components_num);
#endif #endif
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "codec-v4l2-fwht.h" #include "codec-v4l2-fwht.h"
static const struct v4l2_fwht_pixfmt_info v4l2_fwht_pixfmts[] = { static const struct v4l2_fwht_pixfmt_info v4l2_fwht_pixfmts[] = {
{ V4L2_PIX_FMT_GREY, 1, 1, 1, 1, 0, 1, 1, 1},
{ V4L2_PIX_FMT_YUV420, 1, 3, 2, 1, 1, 2, 2, 3}, { V4L2_PIX_FMT_YUV420, 1, 3, 2, 1, 1, 2, 2, 3},
{ V4L2_PIX_FMT_YVU420, 1, 3, 2, 1, 1, 2, 2, 3}, { V4L2_PIX_FMT_YVU420, 1, 3, 2, 1, 1, 2, 2, 3},
{ V4L2_PIX_FMT_YUV422P, 1, 2, 1, 1, 1, 2, 1, 3}, { V4L2_PIX_FMT_YUV422P, 1, 2, 1, 1, 1, 2, 1, 3},
...@@ -75,6 +76,10 @@ int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out) ...@@ -75,6 +76,10 @@ int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
rf.components_num = info->components_num; rf.components_num = info->components_num;
switch (info->id) { switch (info->id) {
case V4L2_PIX_FMT_GREY:
rf.cb = NULL;
rf.cr = NULL;
break;
case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YUV420:
rf.cb = rf.luma + size; rf.cb = rf.luma + size;
rf.cr = rf.cb + size / 4; rf.cr = rf.cb + size / 4;
...@@ -165,6 +170,7 @@ int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out) ...@@ -165,6 +170,7 @@ int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
p_hdr->version = htonl(FWHT_VERSION); p_hdr->version = htonl(FWHT_VERSION);
p_hdr->width = htonl(cf.width); p_hdr->width = htonl(cf.width);
p_hdr->height = htonl(cf.height); p_hdr->height = htonl(cf.height);
flags |= (info->components_num - 1) << FWHT_FL_COMPONENTS_NUM_OFFSET;
if (encoding & FWHT_LUMA_UNENCODED) if (encoding & FWHT_LUMA_UNENCODED)
flags |= FWHT_FL_LUMA_IS_UNCOMPRESSED; flags |= FWHT_FL_LUMA_IS_UNCOMPRESSED;
if (encoding & FWHT_CB_UNENCODED) if (encoding & FWHT_CB_UNENCODED)
...@@ -195,6 +201,8 @@ int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out) ...@@ -195,6 +201,8 @@ int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
struct fwht_cframe_hdr *p_hdr; struct fwht_cframe_hdr *p_hdr;
struct fwht_cframe cf; struct fwht_cframe cf;
u8 *p; u8 *p;
unsigned int components_num = 3;
unsigned int version;
if (!state->info) if (!state->info)
return -EINVAL; return -EINVAL;
...@@ -202,16 +210,16 @@ int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out) ...@@ -202,16 +210,16 @@ int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
p_hdr = (struct fwht_cframe_hdr *)p_in; p_hdr = (struct fwht_cframe_hdr *)p_in;
cf.width = ntohl(p_hdr->width); cf.width = ntohl(p_hdr->width);
cf.height = ntohl(p_hdr->height); cf.height = ntohl(p_hdr->height);
flags = ntohl(p_hdr->flags);
state->colorspace = ntohl(p_hdr->colorspace); version = ntohl(p_hdr->version);
state->xfer_func = ntohl(p_hdr->xfer_func); if (!version || version > FWHT_VERSION) {
state->ycbcr_enc = ntohl(p_hdr->ycbcr_enc); pr_err("version %d is not supported, current version is %d\n",
state->quantization = ntohl(p_hdr->quantization); version, FWHT_VERSION);
cf.rlc_data = (__be16 *)(p_in + sizeof(*p_hdr)); return -EINVAL;
}
if (p_hdr->magic1 != FWHT_MAGIC1 || if (p_hdr->magic1 != FWHT_MAGIC1 ||
p_hdr->magic2 != FWHT_MAGIC2 || p_hdr->magic2 != FWHT_MAGIC2 ||
ntohl(p_hdr->version) != FWHT_VERSION ||
(cf.width & 7) || (cf.height & 7)) (cf.width & 7) || (cf.height & 7))
return -EINVAL; return -EINVAL;
...@@ -219,14 +227,34 @@ int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out) ...@@ -219,14 +227,34 @@ int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
if (cf.width != state->width || cf.height != state->height) if (cf.width != state->width || cf.height != state->height)
return -EINVAL; return -EINVAL;
flags = ntohl(p_hdr->flags);
if (version == FWHT_VERSION) {
components_num = 1 + ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >>
FWHT_FL_COMPONENTS_NUM_OFFSET);
}
state->colorspace = ntohl(p_hdr->colorspace);
state->xfer_func = ntohl(p_hdr->xfer_func);
state->ycbcr_enc = ntohl(p_hdr->ycbcr_enc);
state->quantization = ntohl(p_hdr->quantization);
cf.rlc_data = (__be16 *)(p_in + sizeof(*p_hdr));
if (!(flags & FWHT_FL_CHROMA_FULL_WIDTH)) if (!(flags & FWHT_FL_CHROMA_FULL_WIDTH))
chroma_size /= 2; chroma_size /= 2;
if (!(flags & FWHT_FL_CHROMA_FULL_HEIGHT)) if (!(flags & FWHT_FL_CHROMA_FULL_HEIGHT))
chroma_size /= 2; chroma_size /= 2;
fwht_decode_frame(&cf, &state->ref_frame, flags); fwht_decode_frame(&cf, &state->ref_frame, flags, components_num);
/*
* TODO - handle the case where the compressed stream encodes a
* different format than the requested decoded format.
*/
switch (state->info->id) { switch (state->info->id) {
case V4L2_PIX_FMT_GREY:
memcpy(p_out, state->ref_frame.luma, size);
break;
case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YUV422P: case V4L2_PIX_FMT_YUV422P:
memcpy(p_out, state->ref_frame.luma, size); memcpy(p_out, state->ref_frame.luma, size);
......
...@@ -988,6 +988,16 @@ static int vicodec_start_streaming(struct vb2_queue *q, ...@@ -988,6 +988,16 @@ static int vicodec_start_streaming(struct vb2_queue *q,
unsigned int size = q_data->width * q_data->height; unsigned int size = q_data->width * q_data->height;
const struct v4l2_fwht_pixfmt_info *info = q_data->info; const struct v4l2_fwht_pixfmt_info *info = q_data->info;
unsigned int chroma_div = info->width_div * info->height_div; unsigned int chroma_div = info->width_div * info->height_div;
unsigned int total_planes_size;
/*
* we don't know ahead how many components are in the encoding type
* V4L2_PIX_FMT_FWHT, so we will allocate space for 3 planes.
*/
if (info->id == V4L2_PIX_FMT_FWHT || info->components_num >= 3)
total_planes_size = size + 2 * (size / chroma_div);
else
total_planes_size = size;
q_data->sequence = 0; q_data->sequence = 0;
...@@ -997,10 +1007,8 @@ static int vicodec_start_streaming(struct vb2_queue *q, ...@@ -997,10 +1007,8 @@ static int vicodec_start_streaming(struct vb2_queue *q,
state->width = q_data->width; state->width = q_data->width;
state->height = q_data->height; state->height = q_data->height;
state->ref_frame.width = state->ref_frame.height = 0; state->ref_frame.width = state->ref_frame.height = 0;
state->ref_frame.luma = kvmalloc(size + 2 * size / chroma_div, state->ref_frame.luma = kvmalloc(total_planes_size, GFP_KERNEL);
GFP_KERNEL); ctx->comp_max_size = total_planes_size + sizeof(struct fwht_cframe_hdr);
ctx->comp_max_size = size + 2 * size / chroma_div +
sizeof(struct fwht_cframe_hdr);
state->compressed_frame = kvmalloc(ctx->comp_max_size, GFP_KERNEL); state->compressed_frame = kvmalloc(ctx->comp_max_size, GFP_KERNEL);
if (!state->ref_frame.luma || !state->compressed_frame) { if (!state->ref_frame.luma || !state->compressed_frame) {
kvfree(state->ref_frame.luma); kvfree(state->ref_frame.luma);
...@@ -1008,8 +1016,13 @@ static int vicodec_start_streaming(struct vb2_queue *q, ...@@ -1008,8 +1016,13 @@ static int vicodec_start_streaming(struct vb2_queue *q,
vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED); vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED);
return -ENOMEM; return -ENOMEM;
} }
if (info->id == V4L2_PIX_FMT_FWHT || info->components_num >= 3) {
state->ref_frame.cb = state->ref_frame.luma + size; state->ref_frame.cb = state->ref_frame.luma + size;
state->ref_frame.cr = state->ref_frame.cb + size / chroma_div; state->ref_frame.cr = state->ref_frame.cb + size / chroma_div;
} else {
state->ref_frame.cb = NULL;
state->ref_frame.cr = NULL;
}
ctx->last_src_buf = NULL; ctx->last_src_buf = NULL;
ctx->last_dst_buf = NULL; ctx->last_dst_buf = NULL;
state->gop_cnt = 0; state->gop_cnt = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment