mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
Add initial JPEG decoder.
Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
This commit is contained in:
parent
c350a0809d
commit
75e8a7d6f8
11 changed files with 809 additions and 0 deletions
26
configure.ac
26
configure.ac
|
@ -404,6 +404,32 @@ AC_SUBST(LIBVA_GLX_PKGNAME)
|
|||
AC_SUBST(LIBVA_EXTRA_CFLAGS)
|
||||
AC_SUBST(LIBVA_EXTRA_LIBS)
|
||||
|
||||
dnl Check for JPEG decoding API (0.33+)
|
||||
USE_JPEG_DECODER=0
|
||||
if test "$enable_codecparsers" = "yes"; then
|
||||
AC_CACHE_CHECK([for JPEG decoding API],
|
||||
ac_cv_have_jpeg_decoding_api, [
|
||||
saved_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $LIBVA_CFLAGS"
|
||||
saved_LIBS="$LIBS"
|
||||
LIBS="$CFLAGS $LIBVA_LIBS"
|
||||
AC_TRY_COMPILE(
|
||||
[#include <va/va.h>],
|
||||
[VAPictureParameterBufferJPEG pic_param;
|
||||
VASliceParameterBufferJPEG slice_param;
|
||||
VAIQMatrixBufferJPEG iq_matrix;],
|
||||
[ac_cv_have_jpeg_decoding_api="yes" USE_JPEG_DECODER=1],
|
||||
[ac_cv_have_jpeg_decoding_api="no"]
|
||||
)
|
||||
CFLAGS="$saved_CFLAGS"
|
||||
LIBS="$saved_LIBS"
|
||||
])
|
||||
fi
|
||||
|
||||
AC_DEFINE_UNQUOTED(USE_JPEG_DECODER, $USE_JPEG_DECODER,
|
||||
[Defined to 1 if JPEG decoder is used])
|
||||
AM_CONDITIONAL(USE_JPEG_DECODER, test $USE_JPEG_DECODER -eq 1)
|
||||
|
||||
dnl Check for OpenGL support to vaapisink
|
||||
if test "$enable_vaapisink_glx:$USE_GLX" = "yes:1"; then
|
||||
USE_VAAPISINK_GLX=1
|
||||
|
|
|
@ -168,6 +168,11 @@ libgstvaapi_source_priv_h += \
|
|||
$(NULL)
|
||||
libgstvaapi_cflags += $(GST_CODEC_PARSERS_CFLAGS)
|
||||
libgstvaapi_libs += $(GST_CODEC_PARSERS_LIBS)
|
||||
|
||||
if USE_JPEG_DECODER
|
||||
libgstvaapi_source_c += gstvaapidecoder_jpeg.c
|
||||
libgstvaapi_source_h += gstvaapidecoder_jpeg.h
|
||||
endif
|
||||
endif
|
||||
|
||||
if USE_LOCAL_CODEC_PARSERS
|
||||
|
|
|
@ -243,3 +243,62 @@ gst_vaapi_bitplane_new(GstVaapiDecoder *decoder, guint8 *data, guint data_size)
|
|||
return NULL;
|
||||
return GST_VAAPI_BITPLANE_CAST(object);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* --- JPEG Huffman Tables --- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
GST_VAAPI_CODEC_DEFINE_TYPE(GstVaapiHuffmanTable,
|
||||
gst_vaapi_huffman_table,
|
||||
GST_VAAPI_TYPE_CODEC_OBJECT)
|
||||
|
||||
static void
|
||||
gst_vaapi_huffman_table_destroy(GstVaapiHuffmanTable *huf_table)
|
||||
{
|
||||
vaapi_destroy_buffer(GET_VA_DISPLAY(huf_table), &huf_table->param_id);
|
||||
huf_table->param = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_vaapi_huffman_table_create(
|
||||
GstVaapiHuffmanTable *huf_table,
|
||||
const GstVaapiCodecObjectConstructorArgs *args
|
||||
)
|
||||
{
|
||||
return vaapi_create_buffer(GET_VA_DISPLAY(huf_table),
|
||||
GET_VA_CONTEXT(huf_table),
|
||||
VAHuffmanTableBufferType,
|
||||
args->param_size,
|
||||
args->param,
|
||||
&huf_table->param_id,
|
||||
(void **)&huf_table->param);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_vaapi_huffman_table_init(GstVaapiHuffmanTable *huf_table)
|
||||
{
|
||||
huf_table->param = NULL;
|
||||
huf_table->param_id = VA_INVALID_ID;
|
||||
}
|
||||
|
||||
GstVaapiHuffmanTable *
|
||||
gst_vaapi_huffman_table_new(
|
||||
GstVaapiDecoder *decoder,
|
||||
guint8 *data,
|
||||
guint data_size
|
||||
)
|
||||
{
|
||||
GstVaapiCodecObject *object;
|
||||
|
||||
g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), NULL);
|
||||
|
||||
object = gst_vaapi_codec_object_new(
|
||||
GST_VAAPI_TYPE_HUFFMAN_TABLE,
|
||||
GST_VAAPI_CODEC_BASE(decoder),
|
||||
data, data_size,
|
||||
NULL, 0
|
||||
);
|
||||
if (!object)
|
||||
return NULL;
|
||||
return GST_VAAPI_HUFFMAN_TABLE_CAST(object);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@ typedef struct _GstVaapiIqMatrix GstVaapiIqMatrix;
|
|||
typedef struct _GstVaapiIqMatrixClass GstVaapiIqMatrixClass;
|
||||
typedef struct _GstVaapiBitPlane GstVaapiBitPlane;
|
||||
typedef struct _GstVaapiBitPlaneClass GstVaapiBitPlaneClass;
|
||||
typedef struct _GstVaapiHuffmanTable GstVaapiHuffmanTable;
|
||||
typedef struct _GstVaapiHuffmanTableClass GstVaapiHuffmanTableClass;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* --- Base Codec Object --- */
|
||||
|
@ -256,6 +258,72 @@ GstVaapiBitPlane *
|
|||
gst_vaapi_bitplane_new(GstVaapiDecoder *decoder, guint8 *data, guint data_size)
|
||||
attribute_hidden;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* --- JPEG Huffman Tables --- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#define GST_VAAPI_TYPE_HUFFMAN_TABLE \
|
||||
(gst_vaapi_huffman_table_get_type())
|
||||
|
||||
#define GST_VAAPI_HUFFMAN_TABLE_CAST(obj) \
|
||||
((GstVaapiHuffmanTable *)(obj))
|
||||
|
||||
#define GST_VAAPI_HUFFMAN_TABLE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
GST_VAAPI_TYPE_HUFFMAN_TABLE, \
|
||||
GstVaapiHuffmanTable))
|
||||
|
||||
#define GST_VAAPI_HUFFMAN_TABLE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), \
|
||||
GST_VAAPI_TYPE_HUFFMAN_TABLE, \
|
||||
GstVaapiHuffmanTableClass))
|
||||
|
||||
#define GST_VAAPI_IS_HUFFMAN_TABLE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_HUFFMAN_TABLE))
|
||||
|
||||
#define GST_VAAPI_IS_HUFFMAN_TABLE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_HUFFMAN_TABLE))
|
||||
|
||||
#define GST_VAAPI_HUFFMAN_TABLE_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), \
|
||||
GST_VAAPI_TYPE_HUFFMAN_TABLE, \
|
||||
GstVaapiHuffmanTableClass))
|
||||
|
||||
/**
|
||||
* GstVaapiHuffmanTable:
|
||||
*
|
||||
* A #GstVaapiCodecObject holding huffman table.
|
||||
*/
|
||||
struct _GstVaapiHuffmanTable {
|
||||
/*< private >*/
|
||||
GstVaapiCodecObject parent_instance;
|
||||
VABufferID param_id;
|
||||
|
||||
/*< public >*/
|
||||
gpointer param;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstVaapiHuffmanTableClass:
|
||||
*
|
||||
* The #GstVaapiHuffmanTable base class.
|
||||
*/
|
||||
struct _GstVaapiHuffmanTableClass {
|
||||
/*< private >*/
|
||||
GstVaapiCodecObjectClass parent_class;
|
||||
};
|
||||
|
||||
GType
|
||||
gst_vaapi_huffman_table_get_type(void)
|
||||
attribute_hidden;
|
||||
|
||||
GstVaapiHuffmanTable *
|
||||
gst_vaapi_huffman_table_new(
|
||||
GstVaapiDecoder *decoder,
|
||||
guint8 *data,
|
||||
guint data_size
|
||||
) attribute_hidden;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* --- Helpers to create codec-dependent objects --- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
@ -319,6 +387,10 @@ prefix##_class_init(type##Class *klass) \
|
|||
#define GST_VAAPI_BITPLANE_NEW(decoder, size) \
|
||||
gst_vaapi_bitplane_new(GST_VAAPI_DECODER_CAST(decoder), NULL, size)
|
||||
|
||||
#define GST_VAAPI_HUFFMAN_TABLE_NEW(codec, decoder) \
|
||||
gst_vaapi_huffman_table_new(GST_VAAPI_DECODER_CAST(decoder), \
|
||||
NULL, sizeof(VAHuffmanTableBuffer##codec))
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GST_VAAPI_CODEC_OBJECTS_H */
|
||||
|
|
531
gst-libs/gst/vaapi/gstvaapidecoder_jpeg.c
Normal file
531
gst-libs/gst/vaapi/gstvaapidecoder_jpeg.c
Normal file
|
@ -0,0 +1,531 @@
|
|||
/*
|
||||
* gstvaapidecoder_jpeg.c - JPEG decoder
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:gstvaapidecoder_jpeg
|
||||
* @short_description: JPEG decoder
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include <string.h>
|
||||
#include <gst/codecparsers/gstjpegparser.h>
|
||||
#include "gstvaapidecoder_jpeg.h"
|
||||
#include "gstvaapidecoder_objects.h"
|
||||
#include "gstvaapidecoder_priv.h"
|
||||
#include "gstvaapidisplay_priv.h"
|
||||
#include "gstvaapiobject_priv.h"
|
||||
|
||||
#define DEBUG 1
|
||||
#include "gstvaapidebug.h"
|
||||
|
||||
G_DEFINE_TYPE(GstVaapiDecoderJpeg,
|
||||
gst_vaapi_decoder_jpeg,
|
||||
GST_VAAPI_TYPE_DECODER);
|
||||
|
||||
#define GST_VAAPI_DECODER_JPEG_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE((obj), \
|
||||
GST_VAAPI_TYPE_DECODER_JPEG, \
|
||||
GstVaapiDecoderJpegPrivate))
|
||||
|
||||
struct _GstVaapiDecoderJpegPrivate {
|
||||
GstVaapiProfile profile;
|
||||
guint width;
|
||||
guint height;
|
||||
GstVaapiPicture *current_picture;
|
||||
guint is_opened : 1;
|
||||
guint profile_changed : 1;
|
||||
guint is_constructed : 1;
|
||||
};
|
||||
|
||||
|
||||
static GstVaapiDecoderStatus
|
||||
get_status(GstJpegParserResult result)
|
||||
{
|
||||
GstVaapiDecoderStatus status;
|
||||
|
||||
switch (result) {
|
||||
case GST_JPEG_PARSER_OK:
|
||||
status = GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||
break;
|
||||
case GST_JPEG_PARSER_FRAME_ERROR:
|
||||
case GST_JPEG_PARSER_SCAN_ERROR:
|
||||
case GST_JPEG_PARSER_HUFFMAN_ERROR:
|
||||
case GST_JPEG_PARSER_QUANT_ERROR:
|
||||
status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
|
||||
break;
|
||||
default:
|
||||
status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_vaapi_decoder_jpeg_close(GstVaapiDecoderJpeg *decoder)
|
||||
{
|
||||
GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
|
||||
|
||||
gst_vaapi_picture_replace(&priv->current_picture, NULL);
|
||||
|
||||
/* Reset all */
|
||||
priv->profile = GST_VAAPI_PROFILE_JPEG_BASELINE;
|
||||
priv->width = 0;
|
||||
priv->height = 0;
|
||||
priv->is_opened = FALSE;
|
||||
priv->profile_changed = TRUE;
|
||||
priv->is_constructed = FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_vaapi_decoder_jpeg_open(GstVaapiDecoderJpeg *decoder, GstBuffer *buffer)
|
||||
{
|
||||
gst_vaapi_decoder_jpeg_close(decoder);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_vaapi_decoder_jpeg_destroy(GstVaapiDecoderJpeg *decoder)
|
||||
{
|
||||
gst_vaapi_decoder_jpeg_close(decoder);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_vaapi_decoder_jpeg_create(GstVaapiDecoderJpeg *decoder)
|
||||
{
|
||||
if (!GST_VAAPI_DECODER_CODEC(decoder))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstVaapiDecoderStatus
|
||||
ensure_context(GstVaapiDecoderJpeg *decoder)
|
||||
{
|
||||
GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
|
||||
GstVaapiProfile profiles[2];
|
||||
GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
|
||||
guint i, n_profiles = 0;
|
||||
gboolean reset_context = FALSE;
|
||||
|
||||
if (priv->profile_changed) {
|
||||
GST_DEBUG("profile changed");
|
||||
priv->profile_changed = FALSE;
|
||||
reset_context = TRUE;
|
||||
|
||||
profiles[n_profiles++] = priv->profile;
|
||||
//if (priv->profile == GST_VAAPI_PROFILE_JPEG_EXTENDED)
|
||||
// profiles[n_profiles++] = GST_VAAPI_PROFILE_JPEG_BASELINE;
|
||||
|
||||
for (i = 0; i < n_profiles; i++) {
|
||||
if (gst_vaapi_display_has_decoder(GST_VAAPI_DECODER_DISPLAY(decoder),
|
||||
profiles[i], entrypoint))
|
||||
break;
|
||||
}
|
||||
if (i == n_profiles)
|
||||
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
|
||||
priv->profile = profiles[i];
|
||||
}
|
||||
|
||||
if (reset_context) {
|
||||
reset_context = gst_vaapi_decoder_ensure_context(
|
||||
GST_VAAPI_DECODER(decoder),
|
||||
priv->profile,
|
||||
entrypoint,
|
||||
priv->width, priv->height
|
||||
);
|
||||
if (!reset_context)
|
||||
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
||||
}
|
||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static inline GstVaapiDecoderStatus
|
||||
decode_current_picture(GstVaapiDecoderJpeg *decoder)
|
||||
{
|
||||
GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
|
||||
GstVaapiPicture * const picture = priv->current_picture;
|
||||
GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||
|
||||
if (picture) {
|
||||
if (!gst_vaapi_picture_decode(picture))
|
||||
status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
||||
else if (!gst_vaapi_picture_output(picture))
|
||||
status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
||||
gst_vaapi_picture_replace(&priv->current_picture, NULL);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fill_picture(
|
||||
GstVaapiDecoderJpeg *decoder,
|
||||
GstVaapiPicture *picture,
|
||||
GstJpegImage *jpeg_image
|
||||
)
|
||||
{
|
||||
VAPictureParameterBufferJPEG *pic_param = picture->param;
|
||||
guint i;
|
||||
|
||||
g_assert(pic_param);
|
||||
|
||||
memset(pic_param, 0, sizeof(VAPictureParameterBufferJPEG));
|
||||
pic_param->type = jpeg_image->frame_type;
|
||||
pic_param->sample_precision = jpeg_image->sample_precision;
|
||||
pic_param->image_width = jpeg_image->width;
|
||||
pic_param->image_height = jpeg_image->height;
|
||||
|
||||
/* XXX: ROI + rotation */
|
||||
|
||||
pic_param->num_components = jpeg_image->num_components;
|
||||
for (i = 0; i < pic_param->num_components; i++) {
|
||||
pic_param->components[i].component_id =
|
||||
jpeg_image->components[i].identifier;
|
||||
pic_param->components[i].h_sampling_factor =
|
||||
jpeg_image->components[i].horizontal_factor;
|
||||
pic_param->components[i].v_sampling_factor =
|
||||
jpeg_image->components[i].vertical_factor;
|
||||
pic_param->components[i].quantiser_table_selector =
|
||||
jpeg_image->components[i].quant_table_selector;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fill_quantization_table(
|
||||
GstVaapiDecoderJpeg *decoder,
|
||||
GstVaapiPicture *picture,
|
||||
GstJpegImage *jpeg_image
|
||||
)
|
||||
{
|
||||
VAIQMatrixBufferJPEG *iq_matrix;
|
||||
int i = 0;
|
||||
|
||||
picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(JPEG, decoder);
|
||||
g_assert(picture->iq_matrix);
|
||||
iq_matrix = picture->iq_matrix->param;
|
||||
memset(iq_matrix, 0, sizeof(VAIQMatrixBufferJPEG));
|
||||
for (i = 0; i < GST_JPEG_MAX_COMPONENTS; i++) {
|
||||
iq_matrix->precision[i] = jpeg_image->quant_tables[i].quant_precision;
|
||||
if (iq_matrix->precision[i] == 0) /* 8-bit values*/
|
||||
memcpy(iq_matrix->quantiser_matrix[i], jpeg_image->quant_tables[i].quant_table, 64);
|
||||
else
|
||||
memcpy(iq_matrix->quantiser_matrix[i], jpeg_image->quant_tables[i].quant_table, 128);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fill_huffman_table(
|
||||
GstVaapiDecoderJpeg *decoder,
|
||||
GstVaapiPicture *picture,
|
||||
GstJpegImage *jpeg_image
|
||||
)
|
||||
{
|
||||
VAHuffmanTableBufferJPEG *huffman_table;
|
||||
int i;
|
||||
|
||||
picture->huf_table = GST_VAAPI_HUFFMAN_TABLE_NEW(JPEG, decoder);
|
||||
g_assert(picture->huf_table);
|
||||
huffman_table = picture->huf_table->param;
|
||||
memset(huffman_table, 0, sizeof(VAHuffmanTableBufferJPEG));
|
||||
for (i = 0; i < GST_JPEG_MAX_COMPONENTS; i++) {
|
||||
memcpy(huffman_table->huffman_table[i].dc_bits,
|
||||
jpeg_image->dc_huf_tables[i].huf_bits,
|
||||
16);
|
||||
memcpy(huffman_table->huffman_table[i].dc_huffval,
|
||||
jpeg_image->dc_huf_tables[i].huf_values,
|
||||
16);
|
||||
memcpy(huffman_table->huffman_table[i].ac_bits,
|
||||
jpeg_image->ac_huf_tables[i].huf_bits,
|
||||
16);
|
||||
memcpy(huffman_table->huffman_table[i].ac_huffval,
|
||||
jpeg_image->ac_huf_tables[i].huf_values,
|
||||
256);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
get_max_horizontal_samples(GstJpegImage *jpeg)
|
||||
{
|
||||
guint i, max_factor = 0;
|
||||
|
||||
for (i = 0; i < jpeg->num_components; i++) {
|
||||
if (jpeg->components[i].horizontal_factor > max_factor)
|
||||
max_factor = jpeg->components[i].horizontal_factor;
|
||||
}
|
||||
return max_factor;
|
||||
}
|
||||
|
||||
static guint
|
||||
get_max_vertical_samples(GstJpegImage *jpeg)
|
||||
{
|
||||
guint i, max_factor = 0;
|
||||
|
||||
for (i = 0; i < jpeg->num_components; i++) {
|
||||
if (jpeg->components[i].vertical_factor > max_factor)
|
||||
max_factor = jpeg->components[i].vertical_factor;
|
||||
}
|
||||
return max_factor;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fill_slices(
|
||||
GstVaapiDecoderJpeg *decoder,
|
||||
GstVaapiPicture *picture,
|
||||
GstJpegImage *jpeg_image
|
||||
)
|
||||
{
|
||||
VASliceParameterBufferJPEG *slice_param;
|
||||
GstVaapiSlice *gst_slice;
|
||||
int i;
|
||||
const guint8 *sos_src;
|
||||
guint32 sos_length;
|
||||
guint total_h_samples, total_v_samples;
|
||||
|
||||
while (gst_jpeg_get_left_size(jpeg_image)) {
|
||||
sos_src = gst_jpeg_get_position(jpeg_image);
|
||||
sos_length = gst_jpeg_skip_to_scan_end(jpeg_image);
|
||||
if (!sos_length)
|
||||
break;
|
||||
gst_slice = GST_VAAPI_SLICE_NEW(JPEG, decoder, sos_src, sos_length);
|
||||
slice_param = gst_slice->param;
|
||||
slice_param->num_components = jpeg_image->current_scan.num_components;
|
||||
for (i = 0; i < slice_param->num_components; i++) {
|
||||
slice_param->components[i].component_id = jpeg_image->current_scan.components[i].component_selector;
|
||||
slice_param->components[i].dc_selector = jpeg_image->current_scan.components[i].dc_selector;
|
||||
slice_param->components[i].ac_selector = jpeg_image->current_scan.components[i].ac_selector;
|
||||
}
|
||||
slice_param->restart_interval = jpeg_image->restart_interval;
|
||||
|
||||
if (jpeg_image->current_scan.num_components == 1) { /*non-interleaved*/
|
||||
slice_param->slice_horizontal_position = 0;
|
||||
slice_param->slice_vertical_position = 0;
|
||||
/* Y mcu numbers*/
|
||||
if (slice_param->components[0].component_id == jpeg_image->components[0].identifier) {
|
||||
slice_param->num_mcus = (jpeg_image->width/8)*(jpeg_image->height/8);
|
||||
} else { /*Cr, Cb mcu numbers*/
|
||||
slice_param->num_mcus = (jpeg_image->width/16)*(jpeg_image->height/16);
|
||||
}
|
||||
} else { /* interleaved */
|
||||
slice_param->slice_horizontal_position = 0;
|
||||
slice_param->slice_vertical_position = 0;
|
||||
total_v_samples = get_max_vertical_samples(jpeg_image);
|
||||
total_h_samples = get_max_horizontal_samples(jpeg_image);
|
||||
slice_param->num_mcus = ((jpeg_image->width + total_h_samples*8 - 1)/(total_h_samples*8)) *
|
||||
((jpeg_image->height + total_v_samples*8 -1)/(total_v_samples*8));
|
||||
}
|
||||
|
||||
gst_vaapi_picture_add_slice(picture, gst_slice);
|
||||
if (!gst_jpeg_parse_next_scan(jpeg_image)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (picture->slices && picture->slices->len)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GstVaapiDecoderStatus
|
||||
decode_picture(
|
||||
GstVaapiDecoderJpeg *decoder,
|
||||
guchar *buf,
|
||||
guint buf_size,
|
||||
GstClockTime pts
|
||||
)
|
||||
{
|
||||
GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
|
||||
GstVaapiPicture *picture = NULL;
|
||||
GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||
GstJpegImage jpeg_image;
|
||||
GstJpegParserResult result;
|
||||
|
||||
/* parse jpeg */
|
||||
memset(&jpeg_image, 0, sizeof(jpeg_image));
|
||||
result = gst_jpeg_parse_image(&jpeg_image, buf, buf_size);
|
||||
if (result != GST_JPEG_PARSER_OK) {
|
||||
GST_ERROR("failed to parse image");
|
||||
return get_status(result);
|
||||
}
|
||||
|
||||
/* set info to va parameters in current picture*/
|
||||
priv->profile = GST_VAAPI_PROFILE_JPEG_BASELINE;
|
||||
priv->height = jpeg_image.height;
|
||||
priv->width = jpeg_image.width;
|
||||
|
||||
status = ensure_context(decoder);
|
||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
|
||||
GST_ERROR("failed to reset context");
|
||||
return status;
|
||||
}
|
||||
|
||||
picture = GST_VAAPI_PICTURE_NEW(JPEG, decoder);
|
||||
if (!picture) {
|
||||
GST_ERROR("failed to allocate picture");
|
||||
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
|
||||
}
|
||||
gst_vaapi_picture_replace(&priv->current_picture, picture);
|
||||
gst_vaapi_picture_unref(picture);
|
||||
|
||||
if (!fill_picture(decoder, picture, &jpeg_image))
|
||||
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
||||
|
||||
if (!fill_quantization_table(decoder, picture, &jpeg_image)) {
|
||||
GST_ERROR("failed to fill in quantization table");
|
||||
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
if (!fill_huffman_table(decoder, picture, &jpeg_image)) {
|
||||
GST_ERROR("failed to fill in huffman table");
|
||||
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
if (!fill_slices(decoder, picture, &jpeg_image)) {
|
||||
GST_ERROR("failed to fill in all scans");
|
||||
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Update presentation time */
|
||||
picture->pts = pts;
|
||||
return status;
|
||||
}
|
||||
|
||||
static GstVaapiDecoderStatus
|
||||
decode_buffer(GstVaapiDecoderJpeg *decoder, GstBuffer *buffer)
|
||||
{
|
||||
GstVaapiDecoderStatus status;
|
||||
GstClockTime pts;
|
||||
guchar *buf;
|
||||
guint buf_size;
|
||||
|
||||
buf = GST_BUFFER_DATA(buffer);
|
||||
buf_size = GST_BUFFER_SIZE(buffer);
|
||||
if (!buf && buf_size == 0)
|
||||
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
|
||||
|
||||
pts = GST_BUFFER_TIMESTAMP(buffer);
|
||||
g_assert(GST_CLOCK_TIME_IS_VALID(pts));
|
||||
|
||||
status = decode_picture(decoder, buf, buf_size, pts);
|
||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||
return status;
|
||||
return decode_current_picture(decoder);
|
||||
}
|
||||
|
||||
GstVaapiDecoderStatus
|
||||
gst_vaapi_decoder_jpeg_decode(GstVaapiDecoder *base, GstBuffer *buffer)
|
||||
{
|
||||
GstVaapiDecoderJpeg * const decoder = GST_VAAPI_DECODER_JPEG(base);
|
||||
GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
|
||||
|
||||
if (!priv->is_opened) {
|
||||
priv->is_opened = gst_vaapi_decoder_jpeg_open(decoder, buffer);
|
||||
if (!priv->is_opened)
|
||||
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
|
||||
}
|
||||
return decode_buffer(decoder, buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_vaapi_decoder_jpeg_finalize(GObject *object)
|
||||
{
|
||||
GstVaapiDecoderJpeg * const decoder = GST_VAAPI_DECODER_JPEG(object);
|
||||
|
||||
gst_vaapi_decoder_jpeg_destroy(decoder);
|
||||
|
||||
G_OBJECT_CLASS(gst_vaapi_decoder_jpeg_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_vaapi_decoder_jpeg_constructed(GObject *object)
|
||||
{
|
||||
GstVaapiDecoderJpeg * const decoder = GST_VAAPI_DECODER_JPEG(object);
|
||||
GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
|
||||
GObjectClass *parent_class;
|
||||
|
||||
parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_jpeg_parent_class);
|
||||
if (parent_class->constructed)
|
||||
parent_class->constructed(object);
|
||||
|
||||
priv->is_constructed = gst_vaapi_decoder_jpeg_create(decoder);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_vaapi_decoder_jpeg_class_init(GstVaapiDecoderJpegClass *klass)
|
||||
{
|
||||
GObjectClass * const object_class = G_OBJECT_CLASS(klass);
|
||||
GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
|
||||
|
||||
g_type_class_add_private(klass, sizeof(GstVaapiDecoderJpegPrivate));
|
||||
|
||||
object_class->finalize = gst_vaapi_decoder_jpeg_finalize;
|
||||
object_class->constructed = gst_vaapi_decoder_jpeg_constructed;
|
||||
|
||||
decoder_class->decode = gst_vaapi_decoder_jpeg_decode;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_vaapi_decoder_jpeg_init(GstVaapiDecoderJpeg *decoder)
|
||||
{
|
||||
GstVaapiDecoderJpegPrivate *priv;
|
||||
|
||||
priv = GST_VAAPI_DECODER_JPEG_GET_PRIVATE(decoder);
|
||||
decoder->priv = priv;
|
||||
priv->profile = GST_VAAPI_PROFILE_JPEG_BASELINE;
|
||||
priv->width = 0;
|
||||
priv->height = 0;
|
||||
priv->current_picture = NULL;
|
||||
priv->is_opened = FALSE;
|
||||
priv->profile_changed = TRUE;
|
||||
priv->is_constructed = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_vaapi_decoder_jpeg_new:
|
||||
* @display: a #GstVaapiDisplay
|
||||
* @caps: a #GstCaps holding codec information
|
||||
*
|
||||
* Creates a new #GstVaapiDecoder for JPEG decoding. The @caps can
|
||||
* hold extra information like codec-data and pictured coded size.
|
||||
*
|
||||
* Return value: the newly allocated #GstVaapiDecoder object
|
||||
*/
|
||||
GstVaapiDecoder *
|
||||
gst_vaapi_decoder_jpeg_new(GstVaapiDisplay *display, GstCaps *caps)
|
||||
{
|
||||
GstVaapiDecoderJpeg *decoder;
|
||||
|
||||
g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
|
||||
g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
|
||||
|
||||
decoder = g_object_new(
|
||||
GST_VAAPI_TYPE_DECODER_JPEG,
|
||||
"display", display,
|
||||
"caps", caps,
|
||||
NULL
|
||||
);
|
||||
if (!decoder->priv->is_constructed) {
|
||||
g_object_unref(decoder);
|
||||
return NULL;
|
||||
}
|
||||
return GST_VAAPI_DECODER_CAST(decoder);
|
||||
}
|
88
gst-libs/gst/vaapi/gstvaapidecoder_jpeg.h
Normal file
88
gst-libs/gst/vaapi/gstvaapidecoder_jpeg.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* gstvaapidecoder_jpeg.h - JPEG decoder
|
||||
*
|
||||
* Copyright (C) 2011-2012 Intel Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef GST_VAAPI_DECODER_JPEG_H
|
||||
#define GST_VAAPI_DECODER_JPEG_H
|
||||
|
||||
#include <gst/vaapi/gstvaapidecoder.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_VAAPI_TYPE_DECODER_JPEG \
|
||||
(gst_vaapi_decoder_jpeg_get_type())
|
||||
|
||||
#define GST_VAAPI_DECODER_JPEG(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
GST_VAAPI_TYPE_DECODER_JPEG, \
|
||||
GstVaapiDecoderJpeg))
|
||||
|
||||
#define GST_VAAPI_DECODER_JPEG_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), \
|
||||
GST_VAAPI_TYPE_DECODER_JPEG, \
|
||||
GstVaapiDecoderJpegClass))
|
||||
|
||||
#define GST_VAAPI_IS_DECODER_JPEG(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DECODER_JPEG))
|
||||
|
||||
#define GST_VAAPI_IS_DECODER_JPEG_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DECODER_JPEG))
|
||||
|
||||
#define GST_VAAPI_DECODER_JPEG_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), \
|
||||
GST_VAAPI_TYPE_DECODER_JPEG, \
|
||||
GstVaapiDecoderJpegClass))
|
||||
|
||||
typedef struct _GstVaapiDecoderJpeg GstVaapiDecoderJpeg;
|
||||
typedef struct _GstVaapiDecoderJpegPrivate GstVaapiDecoderJpegPrivate;
|
||||
typedef struct _GstVaapiDecoderJpegClass GstVaapiDecoderJpegClass;
|
||||
|
||||
/**
|
||||
* GstVaapiDecoderJpeg:
|
||||
*
|
||||
* A decoder based on Jpeg.
|
||||
*/
|
||||
struct _GstVaapiDecoderJpeg {
|
||||
/*< private >*/
|
||||
GstVaapiDecoder parent_instance;
|
||||
|
||||
GstVaapiDecoderJpegPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstVaapiDecoderJpegClass:
|
||||
*
|
||||
* A decoder class based on Jpeg.
|
||||
*/
|
||||
struct _GstVaapiDecoderJpegClass {
|
||||
/*< private >*/
|
||||
GstVaapiDecoderClass parent_class;
|
||||
};
|
||||
|
||||
GType
|
||||
gst_vaapi_decoder_jpeg_get_type(void);
|
||||
|
||||
GstVaapiDecoder *
|
||||
gst_vaapi_decoder_jpeg_new(GstVaapiDisplay *display, GstCaps *caps);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GST_VAAPI_DECODER_JPEG_H */
|
||||
|
|
@ -71,6 +71,11 @@ gst_vaapi_picture_destroy(GstVaapiPicture *picture)
|
|||
picture->iq_matrix = NULL;
|
||||
}
|
||||
|
||||
if (picture->huf_table) {
|
||||
gst_mini_object_unref(GST_MINI_OBJECT(picture->huf_table));
|
||||
picture->huf_table = NULL;
|
||||
}
|
||||
|
||||
if (picture->bitplane) {
|
||||
gst_mini_object_unref(GST_MINI_OBJECT(picture->bitplane));
|
||||
picture->bitplane = NULL;
|
||||
|
@ -179,6 +184,7 @@ gst_vaapi_picture_init(GstVaapiPicture *picture)
|
|||
picture->param_size = 0;
|
||||
picture->slices = NULL;
|
||||
picture->iq_matrix = NULL;
|
||||
picture->huf_table = NULL;
|
||||
picture->bitplane = NULL;
|
||||
picture->pts = GST_CLOCK_TIME_NONE;
|
||||
picture->poc = 0;
|
||||
|
@ -264,6 +270,7 @@ gst_vaapi_picture_decode(GstVaapiPicture *picture)
|
|||
{
|
||||
GstVaapiIqMatrix *iq_matrix;
|
||||
GstVaapiBitPlane *bitplane;
|
||||
GstVaapiHuffmanTable *huf_table;
|
||||
VADisplay va_display;
|
||||
VAContextID va_context;
|
||||
VAStatus status;
|
||||
|
@ -293,6 +300,12 @@ gst_vaapi_picture_decode(GstVaapiPicture *picture)
|
|||
&bitplane->data_id, (void **)&bitplane->data))
|
||||
return FALSE;
|
||||
|
||||
huf_table = picture->huf_table;
|
||||
if (huf_table && !do_decode(va_display, va_context,
|
||||
&huf_table->param_id,
|
||||
(void **)&huf_table->param))
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < picture->slices->len; i++) {
|
||||
GstVaapiSlice * const slice = g_ptr_array_index(picture->slices, i);
|
||||
VABufferID va_buffers[2];
|
||||
|
|
|
@ -146,6 +146,7 @@ struct _GstVaapiPicture {
|
|||
gpointer param;
|
||||
GPtrArray *slices;
|
||||
GstVaapiIqMatrix *iq_matrix;
|
||||
GstVaapiHuffmanTable *huf_table;
|
||||
GstVaapiBitPlane *bitplane;
|
||||
GstClockTime pts;
|
||||
gint32 poc;
|
||||
|
|
|
@ -92,6 +92,9 @@ static const GstVaapiProfileMap gst_vaapi_profiles[] = {
|
|||
{ GST_VAAPI_PROFILE_VC1_ADVANCED, VAProfileVC1Advanced,
|
||||
"video/x-wmv, wmvversion=3, format=(fourcc)WVC1", "advanced"
|
||||
},
|
||||
{ GST_VAAPI_PROFILE_JPEG_BASELINE, VAProfileJPEGBaseline,
|
||||
"image/jpeg", "baseline"
|
||||
},
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
|
@ -337,6 +340,9 @@ gst_vaapi_profile_get_codec(GstVaapiProfile profile)
|
|||
case GST_VAAPI_PROFILE_VC1_ADVANCED:
|
||||
codec = GST_VAAPI_CODEC_VC1;
|
||||
break;
|
||||
case GST_VAAPI_PROFILE_JPEG_BASELINE:
|
||||
codec = GST_VAAPI_CODEC_JPEG;
|
||||
break;
|
||||
default:
|
||||
codec = (guint32)profile & GST_MAKE_FOURCC(0xff,0xff,0xff,0);
|
||||
break;
|
||||
|
|
|
@ -50,6 +50,7 @@ enum _GstVaapiCodec {
|
|||
GST_VAAPI_CODEC_H264 = GST_MAKE_FOURCC('2','6','4',0),
|
||||
GST_VAAPI_CODEC_WMV3 = GST_MAKE_FOURCC('W','M','V',0),
|
||||
GST_VAAPI_CODEC_VC1 = GST_MAKE_FOURCC('V','C','1',0),
|
||||
GST_VAAPI_CODEC_JPEG = GST_MAKE_FOURCC('J','P','G',0),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -114,6 +115,7 @@ enum _GstVaapiProfile {
|
|||
GST_VAAPI_PROFILE_VC1_SIMPLE = GST_VAAPI_MAKE_PROFILE(VC1,1),
|
||||
GST_VAAPI_PROFILE_VC1_MAIN = GST_VAAPI_MAKE_PROFILE(VC1,2),
|
||||
GST_VAAPI_PROFILE_VC1_ADVANCED = GST_VAAPI_MAKE_PROFILE(VC1,3),
|
||||
GST_VAAPI_PROFILE_JPEG_BASELINE = GST_VAAPI_MAKE_PROFILE(JPEG,1),
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#endif
|
||||
#if USE_CODEC_PARSERS
|
||||
# include <gst/vaapi/gstvaapidecoder_h264.h>
|
||||
# include <gst/vaapi/gstvaapidecoder_jpeg.h>
|
||||
# include <gst/vaapi/gstvaapidecoder_mpeg2.h>
|
||||
# include <gst/vaapi/gstvaapidecoder_mpeg4.h>
|
||||
# include <gst/vaapi/gstvaapidecoder_vc1.h>
|
||||
|
@ -83,6 +84,7 @@ static const char gst_vaapidecode_sink_caps_str[] =
|
|||
GST_CAPS_CODEC("video/x-h263")
|
||||
GST_CAPS_CODEC("video/x-h264")
|
||||
GST_CAPS_CODEC("video/x-wmv")
|
||||
GST_CAPS_CODEC("image/jpeg")
|
||||
;
|
||||
|
||||
static const char gst_vaapidecode_src_caps_str[] =
|
||||
|
@ -343,6 +345,10 @@ gst_vaapidecode_create(GstVaapiDecode *decode, GstCaps *caps)
|
|||
gst_structure_has_name(structure, "video/x-divx") ||
|
||||
gst_structure_has_name(structure, "video/x-xvid"))
|
||||
decode->decoder = gst_vaapi_decoder_mpeg4_new(dpy, caps);
|
||||
#if USE_JPEG_DECODER
|
||||
else if (gst_structure_has_name(structure, "image/jpeg"))
|
||||
decode->decoder = gst_vaapi_decoder_jpeg_new(dpy, caps);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
if (!decode->decoder)
|
||||
|
|
Loading…
Reference in a new issue