summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>2012-02-10 00:21:04 +0800
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>2012-08-03 11:03:33 +0200
commit715b96d5d35e280da74253732f13d6a8c48244d1 (patch)
treefab6a0d6665ebb2b26325dbfd32bfb9174131ad7
parent1135f66bd942baed2cbbe432abe036a30dad1c19 (diff)
downloadgst-vaapi-715b96d5d35e280da74253732f13d6a8c48244d1.tar.gz
Add initial JPEG decoder.
Cherry picked from commits: 75e8a7d: add initial JPEG decoder 449606e: fix build without JPEG decoder 4e1a354: update to current VA/JPEG decoding API 06be1af: fix build with VA-API < 0.32.0 c7587e8: fix configure check for VA/JPEG decoding API 1139908: update to match latest parser API 4f95b62: add missing doc entries for the JPEG decoder 7c1b9b4: update to the latest VA-API changes (0.32.1+) Signed-off-by: Wind Yuan <feng.yuan@intel.com> Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
-rw-r--r--NEWS1
-rw-r--r--configure.ac28
-rw-r--r--docs/reference/libs/libs-sections.txt16
-rw-r--r--gst-libs/gst/vaapi/Makefile.am5
-rw-r--r--gst-libs/gst/vaapi/gstvaapicodec_objects.c61
-rw-r--r--gst-libs/gst/vaapi/gstvaapicodec_objects.h73
-rw-r--r--gst-libs/gst/vaapi/gstvaapidecoder_jpeg.c710
-rw-r--r--gst-libs/gst/vaapi/gstvaapidecoder_jpeg.h88
-rw-r--r--gst-libs/gst/vaapi/gstvaapidecoder_objects.c13
-rw-r--r--gst-libs/gst/vaapi/gstvaapidecoder_objects.h1
-rw-r--r--gst-libs/gst/vaapi/gstvaapiprofile.c8
-rw-r--r--gst-libs/gst/vaapi/gstvaapiprofile.h2
-rw-r--r--gst/vaapi/gstvaapidecode.c6
13 files changed, 1012 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index 14006b74..be86408e 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,7 @@ Copyright (C) 2011 Collabora
Version 0.3.8 - DD.Jul.2012
* Disable FFmpeg-based decoders by default
+* Add JPEG decoder (based on codecparsers)
* Fix crash when destroying GstVaapiDisplay objects early
* Fix GLX rendering with FBO + texture-from-pixmap (fallback for VA/GLX)
diff --git a/configure.ac b/configure.ac
index dc1c3c21..00552f56 100644
--- a/configure.ac
+++ b/configure.ac
@@ -381,6 +381,34 @@ AC_SUBST(LIBVA_GLX_PKGNAME)
AC_SUBST(LIBVA_EXTRA_CFLAGS)
AC_SUBST(LIBVA_EXTRA_LIBS)
+dnl Check for JPEG decoding API (0.32.1+)
+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_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <va/va.h>]],
+ [[VAPictureParameterBufferJPEGBaseline pic_param;
+ VASliceParameterBufferJPEGBaseline slice_param;
+ VAHuffmanTableBufferJPEGBaseline huffman_table;
+ VAIQMatrixBufferJPEGBaseline 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
diff --git a/docs/reference/libs/libs-sections.txt b/docs/reference/libs/libs-sections.txt
index afcb7938..f7ed15f3 100644
--- a/docs/reference/libs/libs-sections.txt
+++ b/docs/reference/libs/libs-sections.txt
@@ -489,6 +489,22 @@ GST_VAAPI_DECODER_FFMPEG_GET_CLASS
</SECTION>
<SECTION>
+<FILE>gstvaapidecoder_jpeg</FILE>
+<TITLE>GstVaapiDecoderJpeg</TITLE>
+GstVaapiDecoderJpeg
+GstVaapiDecoderJpegClass
+gst_vaapi_decoder_jpeg_new
+<SUBSECTION Standard>
+GST_VAAPI_DECODER_JPEG
+GST_VAAPI_IS_DECODER_JPEG
+GST_VAAPI_TYPE_DECODER_JPEG
+gst_vaapi_decoder_jpeg_get_type
+GST_VAAPI_DECODER_JPEG_CLASS
+GST_VAAPI_IS_DECODER_JPEG_CLASS
+GST_VAAPI_DECODER_JPEG_GET_CLASS
+</SECTION>
+
+<SECTION>
<FILE>gstvaapidecoder_mpeg2</FILE>
<TITLE>GstVaapiDecoderMpeg2</TITLE>
GstVaapiDecoderMpeg2
diff --git a/gst-libs/gst/vaapi/Makefile.am b/gst-libs/gst/vaapi/Makefile.am
index 55f850c2..00259282 100644
--- a/gst-libs/gst/vaapi/Makefile.am
+++ b/gst-libs/gst/vaapi/Makefile.am
@@ -166,6 +166,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
diff --git a/gst-libs/gst/vaapi/gstvaapicodec_objects.c b/gst-libs/gst/vaapi/gstvaapicodec_objects.c
index fd4822da..e79341d0 100644
--- a/gst-libs/gst/vaapi/gstvaapicodec_objects.c
+++ b/gst-libs/gst/vaapi/gstvaapicodec_objects.c
@@ -243,3 +243,64 @@ gst_vaapi_bitplane_new(GstVaapiDecoder *decoder, guint8 *data, guint data_size)
return NULL;
return GST_VAAPI_BITPLANE_CAST(object);
}
+
+/* ------------------------------------------------------------------------- */
+/* --- JPEG Huffman Tables --- */
+/* ------------------------------------------------------------------------- */
+
+#if USE_JPEG_DECODER
+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);
+}
+#endif
diff --git a/gst-libs/gst/vaapi/gstvaapicodec_objects.h b/gst-libs/gst/vaapi/gstvaapicodec_objects.h
index 77adc3a9..a064c159 100644
--- a/gst-libs/gst/vaapi/gstvaapicodec_objects.h
+++ b/gst-libs/gst/vaapi/gstvaapicodec_objects.h
@@ -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 --- */
@@ -260,6 +262,73 @@ GstVaapiBitPlane *
gst_vaapi_bitplane_new(GstVaapiDecoder *decoder, guint8 *data, guint data_size);
/* ------------------------------------------------------------------------- */
+/* --- 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;
+};
+
+G_GNUC_INTERNAL
+GType
+gst_vaapi_huffman_table_get_type(void) G_GNUC_CONST;
+
+G_GNUC_INTERNAL
+GstVaapiHuffmanTable *
+gst_vaapi_huffman_table_new(
+ GstVaapiDecoder *decoder,
+ guint8 *data,
+ guint data_size
+);
+
+/* ------------------------------------------------------------------------- */
/* --- Helpers to create codec-dependent objects --- */
/* ------------------------------------------------------------------------- */
@@ -322,6 +391,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 */
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_jpeg.c b/gst-libs/gst/vaapi/gstvaapidecoder_jpeg.c
new file mode 100644
index 00000000..5cfbe4d6
--- /dev/null
+++ b/gst-libs/gst/vaapi/gstvaapidecoder_jpeg.c
@@ -0,0 +1,710 @@
+/*
+ * 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 "gstvaapicompat.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;
+ GstJpegFrameHdr frame_hdr;
+ GstJpegHuffmanTables huf_tables;
+ GstJpegQuantTables quant_tables;
+ gboolean has_huf_table;
+ gboolean has_quant_table;
+ guint mcu_restart;
+ guint is_opened : 1;
+ guint profile_changed : 1;
+ guint is_constructed : 1;
+};
+
+typedef struct _GstJpegScanSegment GstJpegScanSegment;
+struct _GstJpegScanSegment {
+ guint header_offset;
+ guint header_size;
+ guint data_offset;
+ guint data_size;
+ guint is_valid : 1;
+};
+
+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;
+}
+
+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 gboolean
+decode_current_picture(GstVaapiDecoderJpeg *decoder)
+{
+ GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+ GstVaapiPicture * const picture = priv->current_picture;
+ gboolean success = TRUE;
+
+ if (picture) {
+ if (!gst_vaapi_picture_decode(picture))
+ success = FALSE;
+ else if (!gst_vaapi_picture_output(picture))
+ success = FALSE;
+ gst_vaapi_picture_replace(&priv->current_picture, NULL);
+ }
+ return success;
+}
+
+static gboolean
+fill_picture(
+ GstVaapiDecoderJpeg *decoder,
+ GstVaapiPicture *picture,
+ GstJpegFrameHdr *jpeg_frame_hdr
+)
+{
+ VAPictureParameterBufferJPEGBaseline *pic_param = picture->param;
+ guint i;
+
+ g_assert(pic_param);
+
+ memset(pic_param, 0, sizeof(VAPictureParameterBufferJPEGBaseline));
+ pic_param->picture_width = jpeg_frame_hdr->width;
+ pic_param->picture_height = jpeg_frame_hdr->height;
+
+ pic_param->num_components = jpeg_frame_hdr->num_components;
+ if (jpeg_frame_hdr->num_components > 4)
+ return FALSE;
+ for (i = 0; i < pic_param->num_components; i++) {
+ pic_param->components[i].component_id =
+ jpeg_frame_hdr->components[i].identifier;
+ pic_param->components[i].h_sampling_factor =
+ jpeg_frame_hdr->components[i].horizontal_factor;
+ pic_param->components[i].v_sampling_factor =
+ jpeg_frame_hdr->components[i].vertical_factor;
+ pic_param->components[i].quantiser_table_selector =
+ jpeg_frame_hdr->components[i].quant_table_selector;
+ }
+ return TRUE;
+}
+
+static gboolean
+fill_quantization_table(
+ GstVaapiDecoderJpeg *decoder,
+ GstVaapiPicture *picture
+)
+{
+ GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+ VAIQMatrixBufferJPEGBaseline *iq_matrix;
+ guint i, j, num_tables;
+
+ if (!priv->has_quant_table)
+ gst_jpeg_get_default_quantization_tables(&priv->quant_tables);
+
+ picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(JPEGBaseline, decoder);
+ g_assert(picture->iq_matrix);
+ iq_matrix = picture->iq_matrix->param;
+
+ num_tables = MIN(G_N_ELEMENTS(iq_matrix->quantiser_table),
+ GST_JPEG_MAX_QUANT_ELEMENTS);
+
+ for (i = 0; i < num_tables; i++) {
+ GstJpegQuantTable * const quant_table =
+ &priv->quant_tables.quant_tables[i];
+
+ iq_matrix->load_quantiser_table[i] = quant_table->valid;
+ if (!iq_matrix->load_quantiser_table[i])
+ continue;
+
+ g_assert(quant_table->quant_precision == 0);
+ for (j = 0; j < GST_JPEG_MAX_QUANT_ELEMENTS; j++)
+ iq_matrix->quantiser_table[i][j] = quant_table->quant_table[j];
+ iq_matrix->load_quantiser_table[i] = 1;
+ quant_table->valid = FALSE;
+ }
+ return TRUE;
+}
+
+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 guint
+get_max_horizontal_samples(GstJpegFrameHdr *frame_hdr)
+{
+ guint i, max_factor = 0;
+
+ for (i = 0; i < frame_hdr->num_components; i++) {
+ if (frame_hdr->components[i].horizontal_factor > max_factor)
+ max_factor = frame_hdr->components[i].horizontal_factor;
+ }
+ return max_factor;
+}
+
+static guint
+get_max_vertical_samples(GstJpegFrameHdr *frame_hdr)
+{
+ guint i, max_factor = 0;
+
+ for (i = 0; i < frame_hdr->num_components; i++) {
+ if (frame_hdr->components[i].vertical_factor > max_factor)
+ max_factor = frame_hdr->components[i].vertical_factor;
+ }
+ return max_factor;
+}
+
+static GstVaapiDecoderStatus
+decode_picture(
+ GstVaapiDecoderJpeg *decoder,
+ guint8 profile,
+ guchar *buf,
+ guint buf_size,
+ GstClockTime pts
+)
+{
+ GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+ GstJpegFrameHdr * const frame_hdr = &priv->frame_hdr;
+ GstVaapiPicture *picture;
+ GstVaapiDecoderStatus status;
+
+ switch (profile) {
+ case GST_JPEG_MARKER_SOF_MIN:
+ priv->profile = GST_VAAPI_PROFILE_JPEG_BASELINE;
+ break;
+ default:
+ GST_ERROR("unsupported profile %d", profile);
+ return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
+ }
+
+ memset(frame_hdr, 0, sizeof(*frame_hdr));
+ if (!gst_jpeg_parse_frame_hdr(frame_hdr, buf, buf_size, 0)) {
+ GST_ERROR("failed to parse image");
+ return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+ }
+ priv->height = frame_hdr->height;
+ priv->width = frame_hdr->width;
+
+ status = ensure_context(decoder);
+ if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
+ GST_ERROR("failed to reset context");
+ return status;
+ }
+
+ if (priv->current_picture && !decode_current_picture(decoder))
+ return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+
+ picture = GST_VAAPI_PICTURE_NEW(JPEGBaseline, 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, frame_hdr))
+ return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+
+ /* Update presentation time */
+ picture->pts = pts;
+ return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_huffman_table(
+ GstVaapiDecoderJpeg *decoder,
+ guchar *buf,
+ guint buf_size
+)
+{
+ GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+
+ if (!gst_jpeg_parse_huffman_table(&priv->huf_tables, buf, buf_size, 0)) {
+ GST_DEBUG("failed to parse Huffman table");
+ return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+ }
+ priv->has_huf_table = TRUE;
+ return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_quant_table(
+ GstVaapiDecoderJpeg *decoder,
+ guchar *buf,
+ guint buf_size
+)
+{
+ GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+
+ if (!gst_jpeg_parse_quant_table(&priv->quant_tables, buf, buf_size, 0)) {
+ GST_DEBUG("failed to parse quantization table");
+ return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+ }
+ priv->has_quant_table = TRUE;
+ return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_restart_interval(
+ GstVaapiDecoderJpeg *decoder,
+ guchar *buf,
+ guint buf_size
+)
+{
+ GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+
+ if (!gst_jpeg_parse_restart_interval(&priv->mcu_restart, buf, buf_size, 0)) {
+ GST_DEBUG("failed to parse restart interval");
+ return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+ }
+ return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_scan(
+ GstVaapiDecoderJpeg *decoder,
+ guchar *scan_header,
+ guint scan_header_size,
+ guchar *scan_data,
+ guint scan_data_size)
+{
+ GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+ GstVaapiPicture *picture = priv->current_picture;
+ VASliceParameterBufferJPEGBaseline *slice_param;
+ GstVaapiSlice *gst_slice;
+ guint total_h_samples, total_v_samples;
+ GstJpegScanHdr scan_hdr;
+ guint i;
+
+ if (!picture) {
+ GST_ERROR("There is no VAPicture before decoding scan.");
+ return GST_VAAPI_DECODER_STATUS_ERROR_INVALID_SURFACE;
+ }
+
+ if (!fill_quantization_table(decoder, picture)) {
+ GST_ERROR("failed to fill in quantization table");
+ return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+ }
+
+ if (!fill_huffman_table(decoder, picture)) {
+ GST_ERROR("failed to fill in huffman table");
+ return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+ }
+
+ memset(&scan_hdr, 0, sizeof(scan_hdr));
+ if (!gst_jpeg_parse_scan_hdr(&scan_hdr, scan_header, scan_header_size, 0)) {
+ GST_DEBUG("Jpeg parsed scan failed.");
+ return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+ }
+
+ gst_slice = GST_VAAPI_SLICE_NEW(JPEGBaseline, decoder, scan_data, scan_data_size);
+ gst_vaapi_picture_add_slice(picture, gst_slice);
+
+ slice_param = gst_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;
+ if (scan_hdr.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_selector == priv->frame_hdr.components[0].identifier) {
+ slice_param->num_mcus = (priv->frame_hdr.width/8)*(priv->frame_hdr.height/8);
+ } else { /*Cr, Cb mcu numbers*/
+ slice_param->num_mcus = (priv->frame_hdr.width/16)*(priv->frame_hdr.height/16);
+ }
+ } else { /* interleaved */
+ slice_param->slice_horizontal_position = 0;
+ 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));
+ }
+
+ if (picture->slices && picture->slices->len)
+ return GST_VAAPI_DECODER_STATUS_SUCCESS;
+ return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+}
+
+static GstVaapiDecoderStatus
+decode_buffer(GstVaapiDecoderJpeg *decoder, GstBuffer *buffer)
+{
+ GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+ GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+ GstJpegMarkerSegment seg;
+ GstJpegScanSegment scan_seg;
+ GstClockTime pts;
+ guchar *buf;
+ guint buf_size, ofs;
+ gboolean append_ecs;
+
+ buf = GST_BUFFER_DATA(buffer);
+ buf_size = GST_BUFFER_SIZE(buffer);
+ if (!buf && buf_size == 0)
+ return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+
+ memset(&scan_seg, 0, sizeof(scan_seg));
+
+ pts = GST_BUFFER_TIMESTAMP(buffer);
+ ofs = 0;
+ while (gst_jpeg_parse(&seg, buf, buf_size, ofs)) {
+ if (seg.size < 0) {
+ GST_DEBUG("buffer to short for parsing");
+ return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+ }
+ ofs += seg.size;
+
+ /* Decode scan, if complete */
+ if (seg.marker == GST_JPEG_MARKER_EOI && scan_seg.header_size > 0) {
+ scan_seg.data_size = seg.offset - scan_seg.data_offset;
+ scan_seg.is_valid = TRUE;
+ }
+ if (scan_seg.is_valid) {
+ status = decode_scan(
+ decoder,
+ buf + scan_seg.header_offset,
+ scan_seg.header_size,
+ buf + scan_seg.data_offset,
+ scan_seg.data_size
+ );
+ if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+ break;
+ memset(&scan_seg, 0, sizeof(scan_seg));
+ }
+
+ append_ecs = TRUE;
+ switch (seg.marker) {
+ case GST_JPEG_MARKER_SOI:
+ priv->has_quant_table = FALSE;
+ priv->has_huf_table = FALSE;
+ priv->mcu_restart = 0;
+ status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+ break;
+ case GST_JPEG_MARKER_EOI:
+ status = decode_current_picture(decoder);
+ break;
+ case GST_JPEG_MARKER_DHT:
+ status = decode_huffman_table(decoder, buf + seg.offset, seg.size);
+ break;
+ case GST_JPEG_MARKER_DQT:
+ status = decode_quant_table(decoder, buf + seg.offset, seg.size);
+ break;
+ case GST_JPEG_MARKER_DRI:
+ status = decode_restart_interval(decoder, buf + seg.offset, seg.size);
+ break;
+ case GST_JPEG_MARKER_DAC:
+ GST_ERROR("unsupported arithmetic coding mode");
+ status = GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
+ break;
+ case GST_JPEG_MARKER_SOS:
+ scan_seg.header_offset = seg.offset;
+ scan_seg.header_size = seg.size;
+ scan_seg.data_offset = seg.offset + seg.size;
+ scan_seg.data_size = 0;
+ append_ecs = FALSE;
+ break;
+ default:
+ /* Restart marker */
+ if (seg.marker >= GST_JPEG_MARKER_RST_MIN &&
+ seg.marker <= GST_JPEG_MARKER_RST_MAX) {
+ append_ecs = FALSE;
+ break;
+ }
+
+ /* Frame header */
+ if (seg.marker >= GST_JPEG_MARKER_SOF_MIN &&
+ seg.marker <= GST_JPEG_MARKER_SOF_MAX) {
+ status = decode_picture(
+ decoder,
+ seg.marker,
+ buf + seg.offset, seg.size,
+ pts
+ );
+ break;
+ }
+
+ /* Application segments */
+ if (seg.marker >= GST_JPEG_MARKER_APP_MIN &&
+ seg.marker <= GST_JPEG_MARKER_APP_MAX) {
+ status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+ break;
+ }
+
+ GST_WARNING("unsupported marker (0x%02x)", seg.marker);
+ status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+ break;
+ }
+
+ /* Append entropy coded segments */
+ if (append_ecs)
+ scan_seg.data_size = seg.offset - scan_seg.data_offset;
+
+ if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+ break;
+ }
+ return status;
+}
+
+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->has_huf_table = FALSE;
+ priv->has_quant_table = FALSE;
+ priv->mcu_restart = 0;
+ priv->is_opened = FALSE;
+ priv->profile_changed = TRUE;
+ priv->is_constructed = FALSE;
+ memset(&priv->frame_hdr, 0, sizeof(priv->frame_hdr));
+ memset(&priv->huf_tables, 0, sizeof(priv->huf_tables));
+ memset(&priv->quant_tables, 0, sizeof(priv->quant_tables));
+}
+
+/**
+ * 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);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_jpeg.h b/gst-libs/gst/vaapi/gstvaapidecoder_jpeg.h
new file mode 100644
index 00000000..cd3b975d
--- /dev/null
+++ b/gst-libs/gst/vaapi/gstvaapidecoder_jpeg.h
@@ -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) G_GNUC_CONST;
+
+GstVaapiDecoder *
+gst_vaapi_decoder_jpeg_new(GstVaapiDisplay *display, GstCaps *caps);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DECODER_JPEG_H */
+
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_objects.c b/gst-libs/gst/vaapi/gstvaapidecoder_objects.c
index 4725fac8..5f90fb02 100644
--- a/gst-libs/gst/vaapi/gstvaapidecoder_objects.c
+++ b/gst-libs/gst/vaapi/gstvaapidecoder_objects.c
@@ -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];
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_objects.h b/gst-libs/gst/vaapi/gstvaapidecoder_objects.h
index 571d2138..f7a7ea69 100644
--- a/gst-libs/gst/vaapi/gstvaapidecoder_objects.h
+++ b/gst-libs/gst/vaapi/gstvaapidecoder_objects.h
@@ -146,6 +146,7 @@ struct _GstVaapiPicture {
gpointer param;
GPtrArray *slices;
GstVaapiIqMatrix *iq_matrix;
+ GstVaapiHuffmanTable *huf_table;
GstVaapiBitPlane *bitplane;
GstClockTime pts;
gint32 poc;
diff --git a/gst-libs/gst/vaapi/gstvaapiprofile.c b/gst-libs/gst/vaapi/gstvaapiprofile.c
index 54b7abac..7536c446 100644
--- a/gst-libs/gst/vaapi/gstvaapiprofile.c
+++ b/gst-libs/gst/vaapi/gstvaapiprofile.c
@@ -92,6 +92,11 @@ static const GstVaapiProfileMap gst_vaapi_profiles[] = {
{ GST_VAAPI_PROFILE_VC1_ADVANCED, VAProfileVC1Advanced,
"video/x-wmv, wmvversion=3, format=(fourcc)WVC1", "advanced"
},
+#if VA_CHECK_VERSION(0,32,0)
+ { GST_VAAPI_PROFILE_JPEG_BASELINE, VAProfileJPEGBaseline,
+ "image/jpeg", "baseline"
+ },
+#endif
{ 0, }
};
@@ -337,6 +342,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;
diff --git a/gst-libs/gst/vaapi/gstvaapiprofile.h b/gst-libs/gst/vaapi/gstvaapiprofile.h
index e16bff95..986c9a26 100644
--- a/gst-libs/gst/vaapi/gstvaapiprofile.h
+++ b/gst-libs/gst/vaapi/gstvaapiprofile.h
@@ -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),
};
/**
diff --git a/gst/vaapi/gstvaapidecode.c b/gst/vaapi/gstvaapidecode.c
index 540eaa63..540d15f6 100644
--- a/gst/vaapi/gstvaapidecode.c
+++ b/gst/vaapi/gstvaapidecode.c
@@ -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[] =
@@ -349,6 +351,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)