static gboolean fill_huffman_table( GstVaapiDecoderJpeg *decoder, GstVaapiPicture *picture ) { GstVaapiDecoderJpegPrivate * const priv = decoder->priv; GstJpegHuffmanTables * const huf_tables = &priv->huf_tables; VAHuffmanTableBufferJPEGBaseline *huffman_table; guint i, num_tables; if (!priv->has_huf_table) gst_jpeg_get_default_huffman_tables(&priv->huf_tables); picture->huf_table = GST_VAAPI_HUFFMAN_TABLE_NEW(JPEGBaseline, decoder); g_assert(picture->huf_table); huffman_table = picture->huf_table->param; num_tables = MIN(G_N_ELEMENTS(huffman_table->huffman_table), GST_JPEG_MAX_SCAN_COMPONENTS); for (i = 0; i < num_tables; i++) { huffman_table->load_huffman_table[i] = huf_tables->dc_tables[i].valid && huf_tables->ac_tables[i].valid; if (!huffman_table->load_huffman_table[i]) continue; memcpy(huffman_table->huffman_table[i].num_dc_codes, huf_tables->dc_tables[i].huf_bits, sizeof(huffman_table->huffman_table[i].num_dc_codes)); memcpy(huffman_table->huffman_table[i].dc_values, huf_tables->dc_tables[i].huf_values, sizeof(huffman_table->huffman_table[i].dc_values)); memcpy(huffman_table->huffman_table[i].num_ac_codes, huf_tables->ac_tables[i].huf_bits, sizeof(huffman_table->huffman_table[i].num_ac_codes)); memcpy(huffman_table->huffman_table[i].ac_values, huf_tables->ac_tables[i].huf_values, sizeof(huffman_table->huffman_table[i].ac_values)); memset(huffman_table->huffman_table[i].pad, 0, sizeof(huffman_table->huffman_table[i].pad)); } return TRUE; }
static GstVaapiDecoderStatus decode_scan (GstVaapiDecoderJpeg * decoder, GstJpegSegment * seg) { GstVaapiDecoderJpegPrivate *const priv = &decoder->priv; GstVaapiPicture *const picture = priv->current_picture; GstVaapiSlice *slice; VASliceParameterBufferJPEGBaseline *slice_param; GstJpegScanHdr scan_hdr; guint scan_hdr_size, scan_data_size; guint i, h_max, v_max, mcu_width, mcu_height; if (!VALID_STATE (decoder, GOT_SOF)) return GST_VAAPI_DECODER_STATUS_SUCCESS; scan_hdr_size = (seg->data[seg->offset] << 8) | seg->data[seg->offset + 1]; scan_data_size = seg->size - scan_hdr_size; memset (&scan_hdr, 0, sizeof (scan_hdr)); if (!gst_jpeg_segment_parse_scan_header (seg, &scan_hdr)) { GST_ERROR ("failed to parse scan header"); return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER; } slice = GST_VAAPI_SLICE_NEW (JPEGBaseline, decoder, seg->data + seg->offset + scan_hdr_size, scan_data_size); if (!slice) { GST_ERROR ("failed to allocate slice"); return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; } gst_vaapi_picture_add_slice (picture, slice); if (!VALID_STATE (decoder, GOT_HUF_TABLE)) gst_jpeg_get_default_huffman_tables (&priv->huf_tables); // Update VA Huffman table if it changed for this scan if (huffman_tables_updated (&priv->huf_tables)) { slice->huf_table = GST_VAAPI_HUFFMAN_TABLE_NEW (JPEGBaseline, decoder); if (!slice->huf_table) { GST_ERROR ("failed to allocate Huffman tables"); huffman_tables_reset (&priv->huf_tables); return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; } fill_huffman_table (slice->huf_table, &priv->huf_tables); huffman_tables_reset (&priv->huf_tables); } slice_param = slice->param; slice_param->num_components = scan_hdr.num_components; for (i = 0; i < scan_hdr.num_components; i++) { slice_param->components[i].component_selector = scan_hdr.components[i].component_selector; slice_param->components[i].dc_table_selector = scan_hdr.components[i].dc_selector; slice_param->components[i].ac_table_selector = scan_hdr.components[i].ac_selector; } slice_param->restart_interval = priv->mcu_restart; slice_param->slice_horizontal_position = 0; slice_param->slice_vertical_position = 0; get_max_sampling_factors (&priv->frame_hdr, &h_max, &v_max); mcu_width = 8 * h_max; mcu_height = 8 * v_max; 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; } mcu_width /= fcp->horizontal_factor; mcu_height /= fcp->vertical_factor; } 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; return GST_VAAPI_DECODER_STATUS_SUCCESS; }