mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +00:00
jpeg: fix calculation of MCU count.
Fix calculation of MCU count for image sizes that are not a multiple of 8 pixels in either dimension, but also for non-common sampling factors like 4:2:2 in non-interleaved mode.
This commit is contained in:
parent
5444ab44d2
commit
c171b007ff
1 changed files with 45 additions and 29 deletions
|
@ -372,28 +372,39 @@ fill_huffman_table(GstVaapiHuffmanTable *huf_table,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static guint
|
static void
|
||||||
get_max_horizontal_samples(GstJpegFrameHdr *frame_hdr)
|
get_max_sampling_factors(const GstJpegFrameHdr *frame_hdr,
|
||||||
|
guint *h_max_ptr, guint *v_max_ptr)
|
||||||
{
|
{
|
||||||
guint i, max_factor = 0;
|
guint h_max = frame_hdr->components[0].horizontal_factor;
|
||||||
|
guint v_max = frame_hdr->components[0].vertical_factor;
|
||||||
|
guint i;
|
||||||
|
|
||||||
for (i = 0; i < frame_hdr->num_components; i++) {
|
for (i = 1; i < frame_hdr->num_components; i++) {
|
||||||
if (frame_hdr->components[i].horizontal_factor > max_factor)
|
const GstJpegFrameComponent * const fcp = &frame_hdr->components[i];
|
||||||
max_factor = frame_hdr->components[i].horizontal_factor;
|
if (h_max < fcp->horizontal_factor)
|
||||||
|
h_max = fcp->horizontal_factor;
|
||||||
|
if (v_max < fcp->vertical_factor)
|
||||||
|
v_max = fcp->vertical_factor;
|
||||||
}
|
}
|
||||||
return max_factor;
|
|
||||||
|
if (h_max_ptr)
|
||||||
|
*h_max_ptr = h_max;
|
||||||
|
if (v_max_ptr)
|
||||||
|
*v_max_ptr = v_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
static guint
|
static const GstJpegFrameComponent *
|
||||||
get_max_vertical_samples(GstJpegFrameHdr *frame_hdr)
|
get_component(const GstJpegFrameHdr *frame_hdr, guint selector)
|
||||||
{
|
{
|
||||||
guint i, max_factor = 0;
|
guint i;
|
||||||
|
|
||||||
for (i = 0; i < frame_hdr->num_components; i++) {
|
for (i = 0; i < frame_hdr->num_components; i++) {
|
||||||
if (frame_hdr->components[i].vertical_factor > max_factor)
|
const GstJpegFrameComponent * const fcp = &frame_hdr->components[i];
|
||||||
max_factor = frame_hdr->components[i].vertical_factor;
|
if (fcp->identifier == selector)
|
||||||
|
return fcp;
|
||||||
}
|
}
|
||||||
return max_factor;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstVaapiDecoderStatus
|
static GstVaapiDecoderStatus
|
||||||
|
@ -498,7 +509,7 @@ decode_scan(GstVaapiDecoderJpeg *decoder, GstJpegMarkerSegment *seg,
|
||||||
VASliceParameterBufferJPEGBaseline *slice_param;
|
VASliceParameterBufferJPEGBaseline *slice_param;
|
||||||
GstJpegScanHdr scan_hdr;
|
GstJpegScanHdr scan_hdr;
|
||||||
guint scan_hdr_size, scan_data_size;
|
guint scan_hdr_size, scan_data_size;
|
||||||
guint i, total_h_samples, total_v_samples;
|
guint i, h_max, v_max, mcu_width, mcu_height;
|
||||||
|
|
||||||
if (!VALID_STATE(decoder, GOT_SOF))
|
if (!VALID_STATE(decoder, GOT_SOF))
|
||||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
|
@ -546,23 +557,28 @@ decode_scan(GstVaapiDecoderJpeg *decoder, GstJpegMarkerSegment *seg,
|
||||||
scan_hdr.components[i].ac_selector;
|
scan_hdr.components[i].ac_selector;
|
||||||
}
|
}
|
||||||
slice_param->restart_interval = priv->mcu_restart;
|
slice_param->restart_interval = priv->mcu_restart;
|
||||||
if (scan_hdr.num_components == 1) { /*non-interleaved*/
|
slice_param->slice_horizontal_position = 0;
|
||||||
slice_param->slice_horizontal_position = 0;
|
slice_param->slice_vertical_position = 0;
|
||||||
slice_param->slice_vertical_position = 0;
|
|
||||||
/* Y mcu numbers*/
|
get_max_sampling_factors(&priv->frame_hdr, &h_max, &v_max);
|
||||||
if (slice_param->components[0].component_selector == priv->frame_hdr.components[0].identifier) {
|
mcu_width = 8 * h_max;
|
||||||
slice_param->num_mcus = (priv->frame_hdr.width/8)*(priv->frame_hdr.height/8);
|
mcu_height = 8 * v_max;
|
||||||
} else { /*Cr, Cb mcu numbers*/
|
|
||||||
slice_param->num_mcus = (priv->frame_hdr.width/16)*(priv->frame_hdr.height/16);
|
if (scan_hdr.num_components == 1) { // Non-interleaved
|
||||||
|
const guint Csj = slice_param->components[0].component_selector;
|
||||||
|
const GstJpegFrameComponent * const fcp =
|
||||||
|
get_component(&priv->frame_hdr, Csj);
|
||||||
|
|
||||||
|
if (!fcp || fcp->horizontal_factor == 0 || fcp->vertical_factor == 0) {
|
||||||
|
GST_ERROR("failed to validate image component %u", Csj);
|
||||||
|
return GST_VAAPI_DECODER_STATUS_ERROR_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
} else { /* interleaved */
|
mcu_width /= fcp->horizontal_factor;
|
||||||
slice_param->slice_horizontal_position = 0;
|
mcu_height /= fcp->vertical_factor;
|
||||||
slice_param->slice_vertical_position = 0;
|
|
||||||
total_v_samples = get_max_vertical_samples(&priv->frame_hdr);
|
|
||||||
total_h_samples = get_max_horizontal_samples(&priv->frame_hdr);
|
|
||||||
slice_param->num_mcus = ((priv->frame_hdr.width + total_h_samples*8 - 1)/(total_h_samples*8)) *
|
|
||||||
((priv->frame_hdr.height + total_v_samples*8 -1)/(total_v_samples*8));
|
|
||||||
}
|
}
|
||||||
|
slice_param->num_mcus =
|
||||||
|
((priv->frame_hdr.width + mcu_width - 1) / mcu_width) *
|
||||||
|
((priv->frame_hdr.height + mcu_height - 1) / mcu_height);
|
||||||
|
|
||||||
priv->decoder_state |= GST_JPEG_VIDEO_STATE_GOT_SOS;
|
priv->decoder_state |= GST_JPEG_VIDEO_STATE_GOT_SOS;
|
||||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
|
|
Loading…
Reference in a new issue