Add initial JPEG decoder.
authorWind Yuan <feng.yuan@intel.com>
Thu, 9 Feb 2012 16:21:04 +0000 (00:21 +0800)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Wed, 11 Apr 2012 17:38:12 +0000 (19:38 +0200)
Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
configure.ac
gst-libs/gst/vaapi/Makefile.am
gst-libs/gst/vaapi/gstvaapicodec_objects.c
gst-libs/gst/vaapi/gstvaapicodec_objects.h
gst-libs/gst/vaapi/gstvaapidecoder_jpeg.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_jpeg.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_objects.c
gst-libs/gst/vaapi/gstvaapidecoder_objects.h
gst-libs/gst/vaapi/gstvaapiprofile.c
gst-libs/gst/vaapi/gstvaapiprofile.h
gst/vaapi/gstvaapidecode.c

index d8d4563..4d17ab7 100644 (file)
@@ -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
index d4e3397..394e52a 100644 (file)
@@ -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
index fd4822d..63ba30e 100644 (file)
@@ -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);
+}
index f379f02..8fb0c15 100644 (file)
@@ -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                                                 --- */
@@ -257,6 +259,72 @@ 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                         --- */
 /* ------------------------------------------------------------------------- */
 
@@ -318,6 +386,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
 
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_jpeg.c b/gst-libs/gst/vaapi/gstvaapidecoder_jpeg.c
new file mode 100644 (file)
index 0000000..91c4255
--- /dev/null
@@ -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);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_jpeg.h b/gst-libs/gst/vaapi/gstvaapidecoder_jpeg.h
new file mode 100644 (file)
index 0000000..68dab50
--- /dev/null
@@ -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 */
+
index 4725fac..5f90fb0 100644 (file)
@@ -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];
index 93d8ce2..56a6fde 100644 (file)
@@ -146,6 +146,7 @@ struct _GstVaapiPicture {
     gpointer                    param;
     GPtrArray                  *slices;
     GstVaapiIqMatrix           *iq_matrix;
+    GstVaapiHuffmanTable       *huf_table;
     GstVaapiBitPlane           *bitplane;
     GstClockTime                pts;
     gint32                      poc;
index 54b7aba..f93e628 100644 (file)
@@ -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;
index e16bff9..986c9a2 100644 (file)
@@ -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),
 };
 
 /**
index 638a157..751c158 100644 (file)
@@ -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)