cog: implement chroma-site

Determine chroma site position from the caps and use it when
upsampling/downsampling chroma.
This commit is contained in:
David Schleef 2010-03-15 01:26:25 -07:00
parent 8272df7fb9
commit 8379d20ec6
8 changed files with 256 additions and 34 deletions

View file

@ -32,6 +32,69 @@ shrsw t4, t4, 2
convsuswb d1, t4
.function cogorc_downsample_420_jpeg
.dest 1 d1
.source 2 s1
.source 2 s2
.temp 2 t1
.temp 1 t2
.temp 1 t3
.temp 1 t4
.temp 1 t5
copyw t1, s1
select0wb t2, t1
select1wb t3, t1
avgub t2, t2, t3
copyw t1, s2
select0wb t4, t1
select1wb t5, t1
avgub t4, t4, t5
avgub d1, t2, t4
.function cogorc_downsample_420_mpeg2
.dest 1 d1
.source 2 s1
.source 2 s2
.source 2 s3
.source 2 s4
.temp 1 t1
.temp 1 t2
.temp 1 t3
.temp 2 t4
.temp 2 t5
.temp 2 t6
.temp 2 t7
copyw t4, s1
select0wb t1, t4
select1wb t2, t4
select0wb t3, s2
convubw t4, t1
convubw t5, t2
convubw t6, t3
mullw t5, t5, 2
addw t4, t4, t6
addw t7, t4, t5
copyw t4, s3
select0wb t1, t4
select1wb t2, t4
select0wb t3, s4
convubw t4, t1
convubw t5, t2
convubw t6, t3
mullw t5, t5, 2
addw t4, t4, t6
addw t4, t4, t5
addw t7, t7, t4
addw t7, t7, 4
shrsw t7, t7, 3
convsuswb d1, t7
.function cogorc_downsample_vert_halfsite_2tap
.dest 1 d1
.source 1 s1

View file

@ -864,7 +864,8 @@ cog_frame_convert (CogFrame * dest, CogFrame * src)
}
if ((dest_format & 3) != (frame->format & 3)) {
frame = cog_virt_frame_new_subsample (frame, dest_format, 2);
frame = cog_virt_frame_new_subsample (frame, dest_format,
COG_CHROMA_SITE_MPEG2, 2);
GST_DEBUG ("subsample %p", frame);
}

View file

@ -19,6 +19,12 @@ typedef enum _CogColorMatrix {
COG_COLOR_MATRIX_SDTV
} CogColorMatrix;
typedef enum _CogChromaSite {
COG_CHROMA_SITE_UNKNOWN = 0,
COG_CHROMA_SITE_MPEG2 = 1,
COG_CHROMA_SITE_JPEG
} CogChromaSite;
/* bit pattern:
* 0x100 - 0: normal, 1: indirect (packed)
* 0x001 - horizontal chroma subsampling: 0: 1, 1: 2

View file

@ -1524,6 +1524,9 @@ cog_virt_frame_new_color_matrix_YCbCr_to_YCbCr (CogFrame * vf,
{
CogFrame *virt_frame;
if (in_color_matrix == out_color_matrix)
return vf;
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_U8_444,
vf->width, vf->height);
virt_frame->virt_frame1 = vf;
@ -1593,8 +1596,132 @@ convert_422_420 (CogFrame * frame, void *_dest, int component, int i)
}
}
static void
convert_444_420_mpeg2 (CogFrame * frame, void *_dest, int component, int i)
{
uint8_t *dest = _dest;
uint8_t *src;
if (component == 0) {
src = cog_virt_frame_get_line (frame->virt_frame1, component, i);
orc_memcpy (dest, src, frame->components[component].width);
} else {
uint8_t *dest = _dest;
uint8_t *src1;
uint8_t *src2;
int n_src;
n_src = frame->virt_frame1->components[component].height;
src1 = cog_virt_frame_get_line (frame->virt_frame1, component,
CLAMP (i * 2 + 0, 0, n_src - 1));
src2 = cog_virt_frame_get_line (frame->virt_frame1, component,
CLAMP (i * 2 + 1, 0, n_src - 1));
cogorc_downsample_420_mpeg2 (dest + 1,
(uint16_t *) src1, (uint16_t *) (src1 + 2),
(uint16_t *) src2, (uint16_t *) (src2 + 2),
frame->components[component].width - 1);
{
int j;
int x;
j = 0;
x = 1 * src1[CLAMP (j * 2 - 1, 0, n_src - 1)];
x += 2 * src1[CLAMP (j * 2 + 0, 0, n_src - 1)];
x += 1 * src1[CLAMP (j * 2 + 1, 0, n_src - 1)];
x += 1 * src2[CLAMP (j * 2 - 1, 0, n_src - 1)];
x += 2 * src2[CLAMP (j * 2 + 0, 0, n_src - 1)];
x += 1 * src2[CLAMP (j * 2 + 1, 0, n_src - 1)];
dest[j] = CLAMP ((x + 4) >> 3, 0, 255);
}
}
}
static void
convert_444_420_jpeg (CogFrame * frame, void *_dest, int component, int i)
{
uint8_t *dest = _dest;
uint8_t *src;
if (component == 0) {
src = cog_virt_frame_get_line (frame->virt_frame1, component, i);
orc_memcpy (dest, src, frame->components[component].width);
} else {
uint8_t *dest = _dest;
uint8_t *src1;
uint8_t *src2;
int n_src;
n_src = frame->virt_frame1->components[component].height;
src1 = cog_virt_frame_get_line (frame->virt_frame1, component,
CLAMP (i * 2 + 0, 0, n_src - 1));
src2 = cog_virt_frame_get_line (frame->virt_frame1, component,
CLAMP (i * 2 + 1, 0, n_src - 1));
cogorc_downsample_420_jpeg (dest,
(uint16_t *) src1, (uint16_t *) src2,
frame->components[component].width);
}
}
/* up */
static void
convert_420_444_mpeg2 (CogFrame * frame, void *_dest, int component, int i)
{
uint8_t *dest = _dest;
uint8_t *src;
int n_taps = frame->param1;
if (component == 0) {
src = cog_virt_frame_get_line (frame->virt_frame1, component, i);
orc_memcpy (dest, src, frame->width);
} else {
src = cog_virt_frame_get_line (frame->virt_frame1, component, i / 2);
switch (n_taps) {
default:
case 2:
cogorc_upsample_horiz_cosite (dest, src, src + 1,
frame->components[component].width / 2 - 1);
break;
}
dest[frame->components[component].width - 2] =
src[frame->components[component].width / 2 - 1];
dest[frame->components[component].width - 1] =
src[frame->components[component].width / 2 - 1];
}
}
static void
convert_420_444_jpeg (CogFrame * frame, void *_dest, int component, int i)
{
uint8_t *dest = _dest;
uint8_t *src;
int n_taps = frame->param1;
if (component == 0) {
src = cog_virt_frame_get_line (frame->virt_frame1, component, i);
orc_memcpy (dest, src, frame->width);
} else {
src = cog_virt_frame_get_line (frame->virt_frame1, component, i / 2);
switch (n_taps) {
default:
case 1:
cogorc_upsample_horiz_cosite_1tap (dest, src,
frame->components[component].width / 2 - 1);
break;
}
dest[frame->components[component].width - 2] =
src[frame->components[component].width / 2 - 1];
dest[frame->components[component].width - 1] =
src[frame->components[component].width / 2 - 1];
}
}
static void
convert_422_444 (CogFrame * frame, void *_dest, int component, int i)
{
@ -1609,10 +1736,6 @@ convert_422_444 (CogFrame * frame, void *_dest, int component, int i)
} else {
switch (n_taps) {
default:
case 1:
cogorc_upsample_horiz_cosite_1tap (dest, src,
frame->components[component].width / 2 - 1);
break;
case 2:
cogorc_upsample_horiz_cosite (dest, src, src + 1,
frame->components[component].width / 2 - 1);
@ -1661,7 +1784,8 @@ convert_420_422 (CogFrame * frame, void *_dest, int component, int i)
}
CogFrame *
cog_virt_frame_new_subsample (CogFrame * vf, CogFrameFormat format, int n_taps)
cog_virt_frame_new_subsample (CogFrame * vf, CogFrameFormat format,
CogChromaSite chroma_site, int n_taps)
{
CogFrame *virt_frame;
CogFrameRenderFunc render_line;
@ -1674,14 +1798,11 @@ cog_virt_frame_new_subsample (CogFrame * vf, CogFrameFormat format, int n_taps)
render_line = convert_422_420;
} else if (vf->format == COG_FRAME_FORMAT_U8_444 &&
format == COG_FRAME_FORMAT_U8_420) {
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_U8_422,
vf->width, vf->height);
virt_frame->virt_frame1 = vf;
virt_frame->render_line = convert_444_422;
virt_frame->param1 = n_taps;
vf = virt_frame;
render_line = convert_422_420;
if (chroma_site == COG_CHROMA_SITE_MPEG2) {
render_line = convert_444_420_mpeg2;
} else {
render_line = convert_444_420_jpeg;
}
} else if (vf->format == COG_FRAME_FORMAT_U8_444 &&
format == COG_FRAME_FORMAT_U8_422) {
render_line = convert_444_422;
@ -1690,14 +1811,11 @@ cog_virt_frame_new_subsample (CogFrame * vf, CogFrameFormat format, int n_taps)
render_line = convert_420_422;
} else if (vf->format == COG_FRAME_FORMAT_U8_420 &&
format == COG_FRAME_FORMAT_U8_444) {
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_U8_422,
vf->width, vf->height);
virt_frame->virt_frame1 = vf;
virt_frame->render_line = convert_420_422;
virt_frame->param1 = n_taps;
vf = virt_frame;
render_line = convert_422_444;
if (chroma_site == COG_CHROMA_SITE_MPEG2) {
render_line = convert_420_444_mpeg2;
} else {
render_line = convert_420_444_jpeg;
}
} else if (vf->format == COG_FRAME_FORMAT_U8_422 &&
format == COG_FRAME_FORMAT_U8_444) {
render_line = convert_422_444;

View file

@ -32,7 +32,8 @@ CogFrame * cog_virt_frame_new_color_matrix_RGB_to_YCbCr (CogFrame * vf, CogColor
CogFrame * cog_virt_frame_new_color_matrix_YCbCr_to_YCbCr (CogFrame * vf,
CogColorMatrix in_color_matrix, CogColorMatrix out_color_matrix,
int bits);
CogFrame *cog_virt_frame_new_subsample (CogFrame *vf, CogFrameFormat format, int n_taps);
CogFrame *cog_virt_frame_new_subsample (CogFrame *vf, CogFrameFormat format,
CogChromaSite site, int n_taps);
CogFrame * cog_virt_frame_new_convert_u8 (CogFrame *vf);
CogFrame * cog_virt_frame_new_convert_s16 (CogFrame *vf);

View file

@ -275,6 +275,7 @@ gst_cogcolorspace_caps_remove_format_info (GstCaps * caps)
gst_structure_remove_field (structure, "alpha_mask");
gst_structure_remove_field (structure, "palette_data");
gst_structure_remove_field (structure, "color-matrix");
gst_structure_remove_field (structure, "chroma-site");
}
gst_caps_do_simplify (caps);
@ -365,6 +366,25 @@ gst_cogcolorspace_caps_get_color_matrix (GstCaps * caps)
return COG_COLOR_MATRIX_SDTV;
}
static CogChromaSite
gst_cogcolorspace_caps_get_chroma_site (GstCaps * caps)
{
const char *s;
s = gst_video_parse_caps_chroma_site (caps);
if (s == NULL)
return COG_COLOR_MATRIX_SDTV;
if (strcmp (s, "jpeg") == 0) {
return COG_CHROMA_SITE_JPEG;
} else if (strcmp (s, "mpeg2") == 0) {
return COG_CHROMA_SITE_MPEG2;
}
return COG_CHROMA_SITE_MPEG2;
}
static GstFlowReturn
gst_cogcolorspace_transform (GstBaseTransform * base_transform,
GstBuffer * inbuf, GstBuffer * outbuf)
@ -379,6 +399,8 @@ gst_cogcolorspace_transform (GstBaseTransform * base_transform,
gboolean ret;
CogColorMatrix in_color_matrix;
CogColorMatrix out_color_matrix;
CogChromaSite in_chroma_site;
CogChromaSite out_chroma_site;
g_return_val_if_fail (GST_IS_COGCOLORSPACE (base_transform), GST_FLOW_ERROR);
compress = GST_COGCOLORSPACE (base_transform);
@ -393,6 +415,9 @@ gst_cogcolorspace_transform (GstBaseTransform * base_transform,
in_color_matrix = gst_cogcolorspace_caps_get_color_matrix (inbuf->caps);
out_color_matrix = gst_cogcolorspace_caps_get_color_matrix (outbuf->caps);
in_chroma_site = gst_cogcolorspace_caps_get_chroma_site (inbuf->caps);
out_chroma_site = gst_cogcolorspace_caps_get_chroma_site (outbuf->caps);
frame = gst_cog_buffer_wrap (gst_buffer_ref (inbuf),
in_format, width, height);
out_frame = gst_cog_buffer_wrap (gst_buffer_ref (outbuf),
@ -431,22 +456,24 @@ gst_cogcolorspace_transform (GstBaseTransform * base_transform,
gst_video_format_is_rgb (in_format)) {
frame = cog_virt_frame_new_color_matrix_RGB_to_YCbCr (frame,
out_color_matrix, 8);
frame = cog_virt_frame_new_subsample (frame, new_subsample,
out_chroma_site, (compress->quality >= 3) ? 2 : 1);
}
if (gst_video_format_is_yuv (out_format) &&
gst_video_format_is_yuv (in_format) &&
in_color_matrix != out_color_matrix) {
(in_color_matrix != out_color_matrix ||
in_chroma_site != out_chroma_site)) {
frame = cog_virt_frame_new_subsample (frame, COG_FRAME_FORMAT_U8_444,
(compress->quality >= 5) ? 8 : 6);
in_chroma_site, (compress->quality >= 5) ? 8 : 6);
frame = cog_virt_frame_new_color_matrix_YCbCr_to_YCbCr (frame,
in_color_matrix, out_color_matrix, 8);
}
frame = cog_virt_frame_new_subsample (frame, new_subsample,
(compress->quality >= 3) ? 2 : 1);
if (gst_video_format_is_rgb (out_format) &&
gst_video_format_is_yuv (in_format)) {
frame = cog_virt_frame_new_subsample (frame, new_subsample,
in_chroma_site, (compress->quality >= 3) ? 2 : 1);
frame = cog_virt_frame_new_color_matrix_YCbCr_to_RGB (frame,
in_color_matrix, (compress->quality >= 5) ? 8 : 6);
}

View file

@ -238,18 +238,22 @@ gst_colorconvert_transform_ip (GstBaseTransform * base_transform,
li->format, li->width, li->height);
vf = cog_virt_frame_new_unpack (cog_frame_ref (frame));
vf = cog_virt_frame_new_subsample (vf, COG_FRAME_FORMAT_U8_444, 2);
vf = cog_virt_frame_new_subsample (vf, COG_FRAME_FORMAT_U8_444,
COG_CHROMA_SITE_MPEG2, 2);
vf = cog_virt_frame_new_color_transform (vf);
if (frame->format == COG_FRAME_FORMAT_YUYV) {
vf = cog_virt_frame_new_subsample (vf, COG_FRAME_FORMAT_U8_422, 2);
vf = cog_virt_frame_new_subsample (vf, COG_FRAME_FORMAT_U8_422,
COG_CHROMA_SITE_MPEG2, 2);
vf = cog_virt_frame_new_pack_YUY2 (vf);
} else if (frame->format == COG_FRAME_FORMAT_UYVY) {
vf = cog_virt_frame_new_subsample (vf, COG_FRAME_FORMAT_U8_422, 2);
vf = cog_virt_frame_new_subsample (vf, COG_FRAME_FORMAT_U8_422,
COG_CHROMA_SITE_MPEG2, 2);
vf = cog_virt_frame_new_pack_UYVY (vf);
} else if (frame->format == COG_FRAME_FORMAT_AYUV) {
vf = cog_virt_frame_new_pack_AYUV (vf);
} else if (frame->format == COG_FRAME_FORMAT_U8_420) {
vf = cog_virt_frame_new_subsample (vf, COG_FRAME_FORMAT_U8_420, 2);
vf = cog_virt_frame_new_subsample (vf, COG_FRAME_FORMAT_U8_420,
COG_CHROMA_SITE_MPEG2, 2);
} else {
g_assert_not_reached ();
}

View file

@ -261,13 +261,15 @@ gst_logoinsert_transform_ip (GstBaseTransform * base_transform, GstBuffer * buf)
CogFrame *f;
f = cog_virt_frame_extract_alpha (cog_frame_ref (li->argb_frame));
f = cog_virt_frame_new_subsample (f, frame->format, 2);
f = cog_virt_frame_new_subsample (f, frame->format,
COG_CHROMA_SITE_MPEG2, 2);
li->alpha_frame = cog_frame_realize (f);
f = cog_virt_frame_new_unpack (cog_frame_ref (li->argb_frame));
f = cog_virt_frame_new_color_matrix_RGB_to_YCbCr (f, COG_COLOR_MATRIX_SDTV,
8);
f = cog_virt_frame_new_subsample (f, frame->format, 2);
f = cog_virt_frame_new_subsample (f, frame->format,
COG_CHROMA_SITE_MPEG2, 2);
li->overlay_frame = cog_frame_realize (f);
}