Add initial VC-1 decoder.
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>
Fri, 30 Sep 2011 11:40:11 +0000 (13:40 +0200)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Mon, 16 Jan 2012 10:40:51 +0000 (11:40 +0100)
gst-libs/gst/vaapi/Makefile.am
gst-libs/gst/vaapi/gstvaapidecoder_vc1.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_vc1.h [new file with mode: 0644]
gst/vaapi/gstvaapidecode.c
tests/test-decode.c

index 8023944..50ca49a 100644 (file)
@@ -145,9 +145,11 @@ endif
 if USE_CODEC_PARSERS
 libgstvaapi_source_c   += \
        gstvaapidecoder_mpeg2.c                 \
+       gstvaapidecoder_vc1.c                   \
        $(NULL)
 libgstvaapi_source_h   += \
        gstvaapidecoder_mpeg2.h                 \
+       gstvaapidecoder_vc1.h                   \
        $(NULL)
 libgstvaapi_cflags     += $(GST_CODEC_PARSERS_CFLAGS)
 libgstvaapi_libs       += $(GST_CODEC_PARSERS_LIBS)
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_vc1.c b/gst-libs/gst/vaapi/gstvaapidecoder_vc1.c
new file mode 100644 (file)
index 0000000..ad1e956
--- /dev/null
@@ -0,0 +1,947 @@
+/*
+ *  gstvaapidecoder_vc1.c - VC-1 decoder
+ *
+ *  Copyright (C) 2011 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_vc1
+ * @short_description: VC-1 decoder
+ */
+
+#include "config.h"
+#include <string.h>
+#include <gst/codecparsers/gstvc1parser.h>
+#include "gstvaapidecoder_vc1.h"
+#include "gstvaapidecoder_priv.h"
+#include "gstvaapidisplay_priv.h"
+#include "gstvaapiobject_priv.h"
+#include "gstvaapiutils_tsb.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiDecoderVC1,
+              gst_vaapi_decoder_vc1,
+              GST_VAAPI_TYPE_DECODER);
+
+#define GST_VAAPI_DECODER_VC1_GET_PRIVATE(obj)                  \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_DECODER_VC1,    \
+                                 GstVaapiDecoderVC1Private))
+
+struct _GstVaapiDecoderVC1Private {
+    GstVaapiProfile             profile;
+    guint                       width;
+    guint                       height;
+    guint                       fps_n;
+    guint                       fps_d;
+    GstVC1SeqHdr                seq_hdr;
+    GstVC1EntryPointHdr         entrypoint_hdr;
+    GstVC1FrameHdr              frame_hdr;
+    GstVaapiPicture            *current_picture;
+    GstVaapiPicture            *next_picture;
+    GstVaapiPicture            *prev_picture;
+    GstVaapiTSB                *tsb;
+    GstBuffer                  *sub_buffer;
+    guint                       is_constructed          : 1;
+    guint                       is_opened               : 1;
+    guint                       is_first_field          : 1;
+    guint                       has_entrypoint          : 1;
+    guint                       size_changed            : 1;
+    guint                       profile_changed         : 1;
+    guint                       closed_entry            : 1;
+    guint                       broken_link             : 1;
+};
+
+static GstVaapiDecoderStatus
+get_status(GstVC1ParserResult result)
+{
+    GstVaapiDecoderStatus status;
+
+    switch (result) {
+    case GST_VC1_PARSER_OK:
+        status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+        break;
+    case GST_VC1_PARSER_NO_BDU_END:
+        status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+        break;
+    case GST_VC1_PARSER_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_vc1_close(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+
+    if (priv->current_picture) {
+        gst_vaapi_decoder_free_picture(base_decoder, priv->current_picture);
+        priv->current_picture = NULL;
+    }
+
+    if (priv->next_picture) {
+        gst_vaapi_decoder_free_picture(base_decoder, priv->next_picture);
+        priv->next_picture = NULL;
+    }
+
+    if (priv->prev_picture) {
+        gst_vaapi_decoder_free_picture(base_decoder, priv->prev_picture);
+        priv->prev_picture = NULL;
+    }
+
+    if (priv->sub_buffer) {
+        gst_buffer_unref(priv->sub_buffer);
+        priv->sub_buffer = NULL;
+    }
+
+    if (priv->tsb) {
+        gst_vaapi_tsb_destroy(priv->tsb);
+        priv->tsb = NULL;
+    }
+}
+
+static gboolean
+gst_vaapi_decoder_vc1_open(GstVaapiDecoderVC1 *decoder, GstBuffer *buffer)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+
+    gst_vaapi_decoder_vc1_close(decoder);
+
+    priv->tsb = gst_vaapi_tsb_new();
+    if (!priv->tsb)
+        return FALSE;
+    return TRUE;
+}
+
+static void
+gst_vaapi_decoder_vc1_destroy(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+
+    gst_vaapi_decoder_vc1_close(decoder);
+}
+
+static gboolean
+gst_vaapi_decoder_vc1_create(GstVaapiDecoderVC1 *decoder)
+{
+    if (!GST_VAAPI_DECODER_CODEC(decoder))
+        return FALSE;
+    return TRUE;
+}
+
+static GstVaapiDecoderStatus
+ensure_context(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * 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_VC1_SIMPLE)
+            profiles[n_profiles++] = GST_VAAPI_PROFILE_VC1_MAIN;
+
+        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 (priv->size_changed) {
+        GST_DEBUG("size changed");
+        priv->size_changed = FALSE;
+        reset_context      = TRUE;
+    }
+
+    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
+render_picture(GstVaapiDecoderVC1 *decoder, GstVaapiPicture *picture)
+{
+    GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
+
+    if (!gst_vaapi_decoder_push_surface(base_decoder,
+                                        picture->surface,
+                                        picture->pts))
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_current_picture(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVaapiPicture * const picture = priv->current_picture;
+    GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+
+    if (picture) {
+        if (!gst_vaapi_decoder_decode_picture(base_decoder, picture))
+            status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+        if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture)) {
+            if (priv->prev_picture && priv->next_picture)
+                status = render_picture(decoder, picture);
+            gst_vaapi_decoder_free_picture(base_decoder, picture);
+        }
+        priv->current_picture = NULL;
+    }
+    return status;
+}
+
+static GstVaapiDecoderStatus
+decode_sequence(GstVaapiDecoderVC1 *decoder, guchar *buf, guint buf_size)
+{
+    GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1ParserResult result;
+    GstVaapiProfile profile;
+    guint width, height;
+
+    result = gst_vc1_parse_sequence_header(buf, buf_size, seq_hdr);
+    if (result != GST_VC1_PARSER_OK) {
+        GST_DEBUG("failed to parse sequence layer");
+        return get_status(result);
+    }
+
+    priv->has_entrypoint = FALSE;
+
+    /* Validate profile */
+    switch (seq_hdr->profile) {
+    case GST_VC1_PROFILE_SIMPLE:
+    case GST_VC1_PROFILE_MAIN:
+    case GST_VC1_PROFILE_ADVANCED:
+        break;
+    default:
+        GST_DEBUG("unsupported profile %d", seq_hdr->profile);
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
+    }
+
+#if 0
+    priv->fps_n = seq_hdr->fps_n;
+    priv->fps_d = seq_hdr->fps_d;
+    gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
+#endif
+
+    switch (seq_hdr->profile) {
+    case GST_VC1_PROFILE_SIMPLE:
+    case GST_VC1_PROFILE_MAIN:
+        width  = seq_hdr->struct_c.coded_width;
+        height = seq_hdr->struct_c.coded_height;
+        break;
+    case GST_VC1_PROFILE_ADVANCED:
+        width  = seq_hdr->advanced.max_coded_width;
+        height = seq_hdr->advanced.max_coded_height;
+        break;
+    default:
+        g_assert(0 && "XXX: we already validated the profile above");
+        break;
+    }
+
+    if (priv->width != width) {
+        priv->width = width;
+        priv->size_changed = TRUE;
+    }
+
+    if (priv->height != height) {
+        priv->height = height;
+        priv->size_changed = TRUE;
+    }
+
+    switch (seq_hdr->profile) {
+    case GST_VC1_PROFILE_SIMPLE:
+        profile = GST_VAAPI_PROFILE_VC1_SIMPLE;
+        break;
+    case GST_VC1_PROFILE_MAIN:
+        profile = GST_VAAPI_PROFILE_VC1_MAIN;
+        break;
+    case GST_VC1_PROFILE_ADVANCED:
+        profile = GST_VAAPI_PROFILE_VC1_ADVANCED;
+        break;
+    default:
+        g_assert(0 && "XXX: we already validated the profile above");
+        break;
+    }
+    if (priv->profile != profile) {
+        priv->profile = profile;
+        priv->profile_changed = TRUE;
+    }
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_sequence_end(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVaapiDecoderStatus status;
+
+    if (priv->current_picture) {
+        status = decode_current_picture(decoder);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            return status;
+        status = render_picture(decoder, priv->current_picture);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            return status;
+    }
+
+    if (priv->next_picture) {
+        status = render_picture(decoder, priv->next_picture);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            return status;
+    }
+    return GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
+}
+
+static GstVaapiDecoderStatus
+decode_entry_point(GstVaapiDecoderVC1 *decoder, guchar *buf, guint buf_size)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1EntryPointHdr * const entrypoint_hdr = &priv->entrypoint_hdr;
+    GstVC1ParserResult result;
+
+    result = gst_vc1_parse_entry_point_header(
+        buf, buf_size,
+        entrypoint_hdr,
+        seq_hdr
+    );
+    if (result != GST_VC1_PARSER_OK) {
+        GST_DEBUG("failed to parse entrypoint layer");
+        return get_status(result);
+    }
+
+    if (entrypoint_hdr->coded_size_flag) {
+        priv->width        = entrypoint_hdr->coded_width;
+        priv->height       = entrypoint_hdr->coded_height;
+        priv->size_changed = TRUE;
+    }
+
+    priv->has_entrypoint = TRUE;
+    priv->closed_entry   = entrypoint_hdr->closed_entry;
+    priv->broken_link    = entrypoint_hdr->broken_link;
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static guint
+get_PTYPE(GstVC1FrameHdr *frame_hdr)
+{
+    switch (frame_hdr->ptype) {
+    case GST_VC1_PICTURE_TYPE_I:  return 0;
+    case GST_VC1_PICTURE_TYPE_P:  return 1;
+    case GST_VC1_PICTURE_TYPE_B:  return 2;
+    case GST_VC1_PICTURE_TYPE_BI: return 3;
+    }
+    return 4; /* skipped P-frame */
+}
+
+static inline int
+has_MVTYPEMB_bitplane(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+    guint mvmode, mvmode2;
+
+    if (seq_hdr->profile == GST_VC1_PROFILE_ADVANCED) {
+        GstVC1PicAdvanced * const pic = &frame_hdr->pic.advanced;
+        if (pic->mvtypemb)
+            return 0;
+        mvmode  = pic->mvmode;
+        mvmode2 = pic->mvmode2;
+    }
+    else {
+        GstVC1PicSimpleMain * const pic = &frame_hdr->pic.simple;
+        if (pic->mvtypemb)
+            return 0;
+        mvmode  = pic->mvmode;
+        mvmode2 = pic->mvmode2;
+    }
+    return (frame_hdr->ptype == GST_VC1_PICTURE_TYPE_P &&
+            (mvmode == GST_VC1_MVMODE_MIXED_MV ||
+             (mvmode == GST_VC1_MVMODE_INTENSITY_COMP &&
+              mvmode2 == GST_VC1_MVMODE_MIXED_MV)));
+}
+
+static inline int
+has_SKIPMB_bitplane(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+
+    if (seq_hdr->profile == GST_VC1_PROFILE_ADVANCED) {
+        GstVC1PicAdvanced * const pic = &frame_hdr->pic.advanced;
+        if (pic->skipmb)
+            return 0;
+    }
+    else {
+        GstVC1PicSimpleMain * const pic = &frame_hdr->pic.simple;
+        if (pic->skipmb)
+            return 0;
+    }
+    return (frame_hdr->ptype == GST_VC1_PICTURE_TYPE_P ||
+            frame_hdr->ptype == GST_VC1_PICTURE_TYPE_B);
+}
+
+static inline int
+has_DIRECTMB_bitplane(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+
+    if (seq_hdr->profile == GST_VC1_PROFILE_ADVANCED) {
+        GstVC1PicAdvanced * const pic = &frame_hdr->pic.advanced;
+        if (pic->directmb)
+            return 0;
+    }
+    else {
+        GstVC1PicSimpleMain * const pic = &frame_hdr->pic.simple;
+        if (pic->directmb)
+            return 0;
+    }
+    return frame_hdr->ptype == GST_VC1_PICTURE_TYPE_B;
+}
+
+static inline int
+has_ACPRED_bitplane(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+    GstVC1PicAdvanced * const pic = &frame_hdr->pic.advanced;
+
+    if (seq_hdr->profile != GST_VC1_PROFILE_ADVANCED)
+        return 0;
+    if (pic->acpred)
+        return 0;
+    return (frame_hdr->ptype == GST_VC1_PICTURE_TYPE_I ||
+            frame_hdr->ptype == GST_VC1_PICTURE_TYPE_BI);
+}
+
+static inline int
+has_OVERFLAGS_bitplane(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1EntryPointHdr * const entrypoint_hdr = &priv->entrypoint_hdr;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+    GstVC1PicAdvanced * const pic = &frame_hdr->pic.advanced;
+
+    if (seq_hdr->profile != GST_VC1_PROFILE_ADVANCED)
+        return 0;
+    if (pic->overflags)
+        return 0;
+    return ((frame_hdr->ptype == GST_VC1_PICTURE_TYPE_I ||
+             frame_hdr->ptype == GST_VC1_PICTURE_TYPE_BI) &&
+            (entrypoint_hdr->overlap && frame_hdr->pquant <= 8) &&
+            pic->condover == GST_VC1_CONDOVER_SELECT);
+}
+
+static gboolean
+fill_picture_structc(GstVaapiDecoderVC1 *decoder, GstVaapiPicture *picture)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    VAPictureParameterBufferVC1 * const pic_param = picture->param;
+    GstVC1SeqStructC * const structc = &priv->seq_hdr.struct_c;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+    GstVC1PicSimpleMain * const pic = &frame_hdr->pic.simple;
+
+    /* Fill in VAPictureParameterBufferVC1 (simple/main profile bits) */
+    pic_param->sequence_fields.bits.finterpflag                     = structc->finterpflag;
+    pic_param->sequence_fields.bits.multires                        = structc->multires;
+    pic_param->sequence_fields.bits.overlap                         = structc->overlap;
+    pic_param->sequence_fields.bits.syncmarker                      = structc->syncmarker;
+    pic_param->sequence_fields.bits.rangered                        = structc->rangered;
+    pic_param->sequence_fields.bits.max_b_frames                    = structc->maxbframes;
+    pic_param->conditional_overlap_flag                             = 0; /* advanced profile only */
+    pic_param->fast_uvmc_flag                                       = structc->fastuvmc;
+    pic_param->b_picture_fraction                                   = pic->bfraction;
+    pic_param->cbp_table                                            = pic->cbptab;
+    pic_param->mb_mode_table                                        = 0; /* XXX: interlaced frame */
+    pic_param->range_reduction_frame                                = pic->rangeredfrm;
+    pic_param->rounding_control                                     = 0; /* advanced profile only */
+    pic_param->post_processing                                      = 0; /* advanced profile only */
+    pic_param->picture_resolution_index                             = pic->respic;
+    pic_param->luma_scale                                           = pic->lumscale;
+    pic_param->luma_shift                                           = pic->lumshift;
+    pic_param->raw_coding.flags.mv_type_mb                          = pic->mvtypemb;
+    pic_param->raw_coding.flags.direct_mb                           = pic->directmb;
+    pic_param->raw_coding.flags.skip_mb                             = pic->skipmb;
+    pic_param->bitplane_present.flags.bp_mv_type_mb                 = has_MVTYPEMB_bitplane(decoder);
+    pic_param->bitplane_present.flags.bp_direct_mb                  = has_DIRECTMB_bitplane(decoder);
+    pic_param->bitplane_present.flags.bp_skip_mb                    = has_SKIPMB_bitplane(decoder);
+    pic_param->mv_fields.bits.mv_mode                               = pic->mvmode;
+    pic_param->mv_fields.bits.mv_mode2                              = pic->mvmode2;
+    pic_param->mv_fields.bits.mv_table                              = pic->mvtab;
+    pic_param->mv_fields.bits.extended_mv_flag                      = structc->extended_mv;
+    pic_param->mv_fields.bits.extended_mv_range                     = pic->mvrange;
+    pic_param->transform_fields.bits.variable_sized_transform_flag  = structc->vstransform;
+    pic_param->transform_fields.bits.mb_level_transform_type_flag   = pic->ttmbf;
+    pic_param->transform_fields.bits.frame_level_transform_type     = pic->ttfrm;
+    pic_param->transform_fields.bits.transform_ac_codingset_idx2    = pic->transacfrm2;
+    return TRUE;
+}
+
+static gboolean
+fill_picture_advanced(GstVaapiDecoderVC1 *decoder, GstVaapiPicture *picture)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    VAPictureParameterBufferVC1 * const pic_param = picture->param;
+    GstVC1AdvancedSeqHdr * const adv_hdr = &priv->seq_hdr.advanced;
+    GstVC1EntryPointHdr * const entrypoint_hdr = &priv->entrypoint_hdr;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+    GstVC1PicAdvanced * const pic = &frame_hdr->pic.advanced;
+
+    if (!priv->has_entrypoint)
+        return FALSE;
+
+    /* Fill in VAPictureParameterBufferVC1 (advanced profile bits) */
+    pic_param->sequence_fields.bits.pulldown                        = adv_hdr->pulldown;
+    pic_param->sequence_fields.bits.interlace                       = adv_hdr->interlace;
+    pic_param->sequence_fields.bits.tfcntrflag                      = adv_hdr->tfcntrflag;
+    pic_param->sequence_fields.bits.finterpflag                     = adv_hdr->finterpflag;
+    pic_param->sequence_fields.bits.psf                             = adv_hdr->psf;
+    pic_param->sequence_fields.bits.overlap                         = entrypoint_hdr->overlap;
+    pic_param->entrypoint_fields.bits.broken_link                   = entrypoint_hdr->broken_link;
+    pic_param->entrypoint_fields.bits.closed_entry                  = entrypoint_hdr->closed_entry;
+    pic_param->entrypoint_fields.bits.panscan_flag                  = entrypoint_hdr->panscan_flag;
+    pic_param->entrypoint_fields.bits.loopfilter                    = entrypoint_hdr->loopfilter;
+    pic_param->conditional_overlap_flag                             = pic->condover;
+    pic_param->fast_uvmc_flag                                       = entrypoint_hdr->fastuvmc;
+    pic_param->range_mapping_fields.bits.luma_flag                  = entrypoint_hdr->range_mapy_flag;
+    pic_param->range_mapping_fields.bits.luma                       = entrypoint_hdr->range_mapy;
+    pic_param->range_mapping_fields.bits.chroma_flag                = entrypoint_hdr->range_mapuv_flag;
+    pic_param->range_mapping_fields.bits.chroma                     = entrypoint_hdr->range_mapuv;
+    pic_param->b_picture_fraction                                   = pic->bfraction;
+    pic_param->cbp_table                                            = pic->cbptab;
+    pic_param->mb_mode_table                                        = 0; /* XXX: interlaced frame */
+    pic_param->range_reduction_frame                                = 0; /* simple/main profile only */
+    pic_param->rounding_control                                     = pic->rndctrl;
+    pic_param->post_processing                                      = pic->postproc;
+    pic_param->picture_resolution_index                             = 0; /* simple/main profile only */
+    pic_param->luma_scale                                           = pic->lumscale;
+    pic_param->luma_shift                                           = pic->lumshift;
+    pic_param->picture_fields.bits.frame_coding_mode                = pic->fcm;
+    pic_param->picture_fields.bits.top_field_first                  = pic->tff;
+    pic_param->picture_fields.bits.is_first_field                   = pic->fcm == 0; /* XXX: interlaced frame */
+    pic_param->picture_fields.bits.intensity_compensation           = pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP;
+    pic_param->raw_coding.flags.mv_type_mb                          = pic->mvtypemb;
+    pic_param->raw_coding.flags.direct_mb                           = pic->directmb;
+    pic_param->raw_coding.flags.skip_mb                             = pic->skipmb;
+    pic_param->raw_coding.flags.ac_pred                             = pic->acpred;
+    pic_param->raw_coding.flags.overflags                           = pic->overflags;
+    pic_param->bitplane_present.flags.bp_mv_type_mb                 = has_MVTYPEMB_bitplane(decoder);
+    pic_param->bitplane_present.flags.bp_direct_mb                  = has_DIRECTMB_bitplane(decoder);
+    pic_param->bitplane_present.flags.bp_skip_mb                    = has_SKIPMB_bitplane(decoder);
+    pic_param->bitplane_present.flags.bp_ac_pred                    = has_ACPRED_bitplane(decoder);
+    pic_param->bitplane_present.flags.bp_overflags                  = has_OVERFLAGS_bitplane(decoder);
+    pic_param->reference_fields.bits.reference_distance_flag        = entrypoint_hdr->refdist_flag;
+    pic_param->mv_fields.bits.mv_mode                               = pic->mvmode;
+    pic_param->mv_fields.bits.mv_mode2                              = pic->mvmode2;
+    pic_param->mv_fields.bits.mv_table                              = pic->mvtab;
+    pic_param->mv_fields.bits.extended_mv_flag                      = entrypoint_hdr->extended_mv;
+    pic_param->mv_fields.bits.extended_mv_range                     = pic->mvrange;
+    pic_param->mv_fields.bits.extended_dmv_flag                     = entrypoint_hdr->extended_dmv;
+    pic_param->pic_quantizer_fields.bits.dquant                     = entrypoint_hdr->dquant;
+    pic_param->pic_quantizer_fields.bits.quantizer                  = entrypoint_hdr->quantizer;
+    pic_param->transform_fields.bits.variable_sized_transform_flag  = entrypoint_hdr->vstransform;
+    pic_param->transform_fields.bits.mb_level_transform_type_flag   = pic->ttmbf;
+    pic_param->transform_fields.bits.frame_level_transform_type     = pic->ttfrm;
+    pic_param->transform_fields.bits.transform_ac_codingset_idx2    = pic->transacfrm2;
+    return TRUE;
+}
+
+static gboolean
+fill_picture(GstVaapiDecoderVC1 *decoder, GstVaapiPicture *picture)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    VAPictureParameterBufferVC1 * const pic_param = picture->param;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+
+    /* Fill in VAPictureParameterBufferVC1 (common fields) */
+    pic_param->forward_reference_picture                            = VA_INVALID_ID;
+    pic_param->backward_reference_picture                           = VA_INVALID_ID;
+    pic_param->inloop_decoded_picture                               = VA_INVALID_ID;
+    pic_param->sequence_fields.value                                = 0;
+#if VA_CHECK_VERSION(0,32,0)
+    pic_param->sequence_fields.bits.profile                         = seq_hdr->profile;
+#endif
+    pic_param->coded_width                                          = priv->width;
+    pic_param->coded_height                                         = priv->height;
+    pic_param->entrypoint_fields.value                              = 0;
+    pic_param->range_mapping_fields.value                           = 0;
+    pic_param->picture_fields.value                                 = 0;
+    pic_param->picture_fields.bits.picture_type                     = get_PTYPE(frame_hdr);
+    pic_param->raw_coding.value                                     = 0;
+    pic_param->bitplane_present.value                               = 0;
+    pic_param->reference_fields.value                               = 0;
+    pic_param->mv_fields.value                                      = 0;
+    pic_param->pic_quantizer_fields.value                           = 0;
+    pic_param->pic_quantizer_fields.bits.half_qp                    = frame_hdr->halfqp;
+    pic_param->pic_quantizer_fields.bits.pic_quantizer_scale        = frame_hdr->pquant;
+    pic_param->pic_quantizer_fields.bits.pic_quantizer_type         = frame_hdr->pquantizer;
+    pic_param->pic_quantizer_fields.bits.dq_frame                   = frame_hdr->vopdquant.dquantfrm;
+    pic_param->pic_quantizer_fields.bits.dq_profile                 = frame_hdr->vopdquant.dqprofile;
+    pic_param->pic_quantizer_fields.bits.dq_sb_edge                 = frame_hdr->vopdquant.dqsbedge;
+    pic_param->pic_quantizer_fields.bits.dq_db_edge                 = frame_hdr->vopdquant.dqsbedge;
+    pic_param->pic_quantizer_fields.bits.dq_binary_level            = frame_hdr->vopdquant.dqbilevel;
+    pic_param->pic_quantizer_fields.bits.alt_pic_quantizer          = frame_hdr->vopdquant.altpquant;
+    pic_param->transform_fields.value                               = 0;
+    pic_param->transform_fields.bits.transform_ac_codingset_idx1    = frame_hdr->transacfrm;
+    pic_param->transform_fields.bits.intra_transform_dc_table       = frame_hdr->transdctab;
+
+    if (seq_hdr->profile == GST_VC1_PROFILE_ADVANCED) {
+        if (!fill_picture_advanced(decoder, picture))
+            return FALSE;
+    }
+    else {
+        if (!fill_picture_structc(decoder, picture))
+            return FALSE;
+    }
+
+    switch (picture->type) {
+    case GST_VAAPI_PICTURE_TYPE_B:
+        if (priv->next_picture)
+            pic_param->backward_reference_picture = priv->next_picture->surface_id;
+        // fall-through
+    case GST_VAAPI_PICTURE_TYPE_P:
+        if (priv->prev_picture)
+            pic_param->forward_reference_picture = priv->prev_picture->surface_id;
+        break;
+    default:
+        break;
+    }
+    return TRUE;
+}
+
+static GstVaapiDecoderStatus
+decode_frame(GstVaapiDecoderVC1 *decoder, guchar *buf, guint buf_size)
+{
+    GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+    GstVC1ParserResult result;
+    GstVaapiPicture *picture;
+    GstVaapiSlice *slice;
+    GstVaapiDecoderStatus status;
+    VASliceParameterBufferVC1 *slice_param;
+
+    status = ensure_context(decoder);
+    if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
+        GST_DEBUG("failed to reset context");
+        return status;
+    }
+
+    if (priv->current_picture) {
+        status = decode_current_picture(decoder);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            return status;
+    }
+
+    priv->current_picture = gst_vaapi_decoder_new_picture(base_decoder);
+    if (!priv->current_picture) {
+        GST_DEBUG("failed to allocate picture");
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+    picture = priv->current_picture;
+
+    memset(frame_hdr, 0, sizeof(*frame_hdr));
+    result = gst_vc1_parse_frame_header(buf, buf_size, frame_hdr, seq_hdr, NULL);
+    if (result != GST_VC1_PARSER_OK) {
+        GST_DEBUG("failed to parse frame layer");
+        return get_status(result);
+    }
+
+    switch (frame_hdr->ptype) {
+    case GST_VC1_PICTURE_TYPE_I:
+        picture->type   = GST_VAAPI_PICTURE_TYPE_I;
+        picture->flags |= GST_VAAPI_PICTURE_REFERENCE;
+        break;
+    case GST_VC1_PICTURE_TYPE_SKIPPED:
+        picture->flags |= GST_VAAPI_PICTURE_SKIPPED;
+        // fall-through
+    case GST_VC1_PICTURE_TYPE_P:
+        picture->type   = GST_VAAPI_PICTURE_TYPE_P;
+        picture->flags |= GST_VAAPI_PICTURE_REFERENCE;
+        break;
+    case GST_VC1_PICTURE_TYPE_B:
+        picture->type   = GST_VAAPI_PICTURE_TYPE_B;
+        break;
+    case GST_VC1_PICTURE_TYPE_BI:
+        picture->type   = GST_VAAPI_PICTURE_TYPE_BI;
+        break;
+    default:
+        GST_DEBUG("unsupported picture type %d", frame_hdr->ptype);
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+    }
+
+    /* Update reference pictures */
+    if (GST_VAAPI_PICTURE_IS_REFERENCE(picture)) {
+        if (priv->prev_picture) {
+            gst_vaapi_decoder_free_picture(base_decoder, priv->prev_picture);
+            priv->prev_picture = NULL;
+        }
+        if (priv->next_picture) {
+            priv->prev_picture = priv->next_picture;
+            priv->next_picture = NULL;
+            status = render_picture(decoder, priv->prev_picture);
+        }
+        priv->next_picture = picture;
+    }
+
+    if (!fill_picture(decoder, picture))
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+
+    slice = gst_vaapi_decoder_new_slice(base_decoder, picture, buf, buf_size);
+    if (!slice) {
+        GST_DEBUG("failed to allocate slice");
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+
+    /* Fill in VASliceParameterBufferVC1 */
+    slice_param                            = slice->param;
+    slice_param->macroblock_offset         = frame_hdr->header_size;
+    slice_param->slice_vertical_position   = 0;
+
+    /* Decode picture right away, we got the full frame */
+    return decode_current_picture(decoder);
+}
+
+static GstVaapiDecoderStatus
+decode_buffer(GstVaapiDecoderVC1 *decoder, GstBuffer *buffer)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVaapiDecoderStatus status;
+    GstVC1ParserResult result;
+    GstVC1BDU bdu;
+    guchar *buf;
+    guint buf_size, bdu_size, ofs;
+
+    buf      = GST_BUFFER_DATA(buffer);
+    buf_size = GST_BUFFER_SIZE(buffer);
+    if (!buf && buf_size == 0)
+        return decode_sequence_end(decoder);
+
+    gst_vaapi_tsb_push(priv->tsb, buffer);
+
+    if (priv->sub_buffer) {
+        buffer = gst_buffer_merge(priv->sub_buffer, buffer);
+        if (!buffer)
+            return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+        gst_buffer_unref(priv->sub_buffer);
+        priv->sub_buffer = NULL;
+    }
+
+    buf      = GST_BUFFER_DATA(buffer);
+    buf_size = GST_BUFFER_SIZE(buffer);
+    ofs      = 0;
+    do {
+        result = gst_vc1_identify_next_bdu(
+            buf + ofs,
+            buf_size - ofs,
+            &bdu
+        );
+        status = get_status(result);
+
+        if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA) {
+            priv->sub_buffer = gst_buffer_create_sub(buffer, ofs, buf_size - ofs);
+            break;
+        }
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            break;
+
+        ofs += bdu.offset;
+        switch (bdu.type) {
+        case GST_VC1_SEQUENCE:
+            status = decode_sequence(decoder, buf + ofs, bdu.size);
+            break;
+        case GST_VC1_ENTRYPOINT:
+            status = decode_entry_point(decoder, buf + ofs, bdu.size);
+            break;
+        case GST_VC1_FRAME:
+            status = decode_frame(decoder, buf + ofs, bdu.size);
+            break;
+        case GST_VC1_SLICE:
+            GST_DEBUG("decode slice");
+            break;
+        case GST_VC1_END_OF_SEQ:
+            status = decode_sequence_end(decoder);
+            break;
+        default:
+            GST_DEBUG("unsupported BDU type %d", bdu.type);
+            status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+            break;
+        }
+        ofs += bdu.size;
+    } while (status == GST_VAAPI_DECODER_STATUS_SUCCESS);
+    return status;
+}
+
+GstVaapiDecoderStatus
+gst_vaapi_decoder_vc1_decode(GstVaapiDecoder *base, GstBuffer *buffer)
+{
+    GstVaapiDecoderVC1 * const decoder = GST_VAAPI_DECODER_VC1(base);
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+
+    g_return_val_if_fail(priv->is_constructed,
+                         GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED);
+
+    if (!priv->is_opened) {
+        priv->is_opened = gst_vaapi_decoder_vc1_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_vc1_finalize(GObject *object)
+{
+    GstVaapiDecoderVC1 * const decoder = GST_VAAPI_DECODER_VC1(object);
+
+    gst_vaapi_decoder_vc1_destroy(decoder);
+
+    G_OBJECT_CLASS(gst_vaapi_decoder_vc1_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_decoder_vc1_constructed(GObject *object)
+{
+    GstVaapiDecoderVC1 * const decoder = GST_VAAPI_DECODER_VC1(object);
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GObjectClass *parent_class;
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_vc1_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+
+    priv->is_constructed = gst_vaapi_decoder_vc1_create(decoder);
+}
+
+static void
+gst_vaapi_decoder_vc1_class_init(GstVaapiDecoderVC1Class *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(GstVaapiDecoderVC1Private));
+
+    object_class->finalize      = gst_vaapi_decoder_vc1_finalize;
+    object_class->constructed   = gst_vaapi_decoder_vc1_constructed;
+
+    decoder_class->decode       = gst_vaapi_decoder_vc1_decode;
+}
+
+static void
+gst_vaapi_decoder_vc1_init(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private *priv;
+
+    priv                        = GST_VAAPI_DECODER_VC1_GET_PRIVATE(decoder);
+    decoder->priv               = priv;
+    priv->width                 = 0;
+    priv->height                = 0;
+    priv->fps_n                 = 0;
+    priv->fps_d                 = 0;
+    priv->profile               = (GstVaapiProfile)0;
+    priv->current_picture       = NULL;
+    priv->next_picture          = NULL;
+    priv->prev_picture          = NULL;
+    priv->tsb                   = NULL;
+    priv->sub_buffer            = NULL;
+    priv->is_constructed        = FALSE;
+    priv->is_opened             = FALSE;
+    priv->is_first_field        = FALSE;
+    priv->has_entrypoint        = FALSE;
+    priv->size_changed          = FALSE;
+    priv->profile_changed       = FALSE;
+    priv->closed_entry          = FALSE;
+    priv->broken_link           = FALSE;
+}
+
+/**
+ * gst_vaapi_decoder_vc1_new:
+ * @display: a #GstVaapiDisplay
+ * @caps: a #GstCaps holding codec information
+ *
+ * Creates a new #GstVaapiDecoder for VC-1 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_vc1_new(GstVaapiDisplay *display, GstCaps *caps)
+{
+    GstVaapiDecoderVC1 *decoder;
+
+    static const GstVaapiCodecInfo codec_info = {
+        .pic_size               = sizeof(GstVaapiPicture),
+        .slice_size             = sizeof(GstVaapiSlice),
+        .pic_param_size         = sizeof(VAPictureParameterBufferVC1),
+        .slice_param_size       = sizeof(VASliceParameterBufferVC1),
+        .iq_matrix_size         = 0,
+    };
+
+    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_VC1,
+        "display",      display,
+        "caps",         caps,
+        "codec-info",   &codec_info,
+        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_vc1.h b/gst-libs/gst/vaapi/gstvaapidecoder_vc1.h
new file mode 100644 (file)
index 0000000..b877227
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ *  gstvaapidecoder_vc1.h - VC-1 decoder
+ *
+ *  Copyright (C) 2011 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_VC1_H
+#define GST_VAAPI_DECODER_VC1_H
+
+#include <gst/vaapi/gstvaapidecoder.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_DECODER_VC1 \
+    (gst_vaapi_decoder_vc1_get_type())
+
+#define GST_VAAPI_DECODER_VC1(obj)                              \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_DECODER_VC1,     \
+                                GstVaapiDecoderVC1))
+
+#define GST_VAAPI_DECODER_VC1_CLASS(klass)                      \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_DECODER_VC1,        \
+                             GstVaapiDecoderVC1Class))
+
+#define GST_VAAPI_IS_DECODER_VC1(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DECODER_VC1))
+
+#define GST_VAAPI_IS_DECODER_VC1_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DECODER_VC1))
+
+#define GST_VAAPI_DECODER_VC1_GET_CLASS(obj)                    \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_DECODER_VC1,      \
+                               GstVaapiDecoderVC1Class))
+
+typedef struct _GstVaapiDecoderVC1              GstVaapiDecoderVC1;
+typedef struct _GstVaapiDecoderVC1Private       GstVaapiDecoderVC1Private;
+typedef struct _GstVaapiDecoderVC1Class         GstVaapiDecoderVC1Class;
+
+/**
+ * GstVaapiDecoderVC1:
+ *
+ * A decoder based on VC1.
+ */
+struct _GstVaapiDecoderVC1 {
+    /*< private >*/
+    GstVaapiDecoder parent_instance;
+
+    GstVaapiDecoderVC1Private *priv;
+};
+
+/**
+ * GstVaapiDecoderVC1Class:
+ *
+ * A decoder class based on VC1.
+ */
+struct _GstVaapiDecoderVC1Class {
+    /*< private >*/
+    GstVaapiDecoderClass parent_class;
+};
+
+GType
+gst_vaapi_decoder_vc1_get_type(void);
+
+GstVaapiDecoder *
+gst_vaapi_decoder_vc1_new(GstVaapiDisplay *display, GstCaps *caps);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DECODER_VC1_H */
index 6077502..49fa80e 100644 (file)
@@ -51,6 +51,7 @@
 #endif
 #if USE_CODEC_PARSERS
 # include <gst/vaapi/gstvaapidecoder_mpeg2.h>
+# include <gst/vaapi/gstvaapidecoder_vc1.h>
 #endif
 
 /* Favor codecparsers-based decoders for 0.3.x series */
@@ -315,6 +316,8 @@ gst_vaapidecode_create(GstVaapiDecode *decode, GstCaps *caps)
             if (version == 2)
                 decode->decoder = gst_vaapi_decoder_mpeg2_new(dpy, caps);
         }
+        else if (gst_structure_has_name(structure, "video/x-wmv"))
+            decode->decoder = gst_vaapi_decoder_vc1_new(dpy, caps);
 #endif
     }
     if (!decode->decoder)
index 0f37286..835400b 100644 (file)
@@ -34,6 +34,7 @@
 #endif
 #if USE_CODEC_PARSERS
 # include <gst/vaapi/gstvaapidecoder_mpeg2.h>
+# include <gst/vaapi/gstvaapidecoder_vc1.h>
 #endif
 
 /* Set to 1 to check display cache works (shared VA display) */
@@ -164,6 +165,9 @@ main(int argc, char *argv[])
         case GST_VAAPI_CODEC_MPEG2:
             decoder = gst_vaapi_decoder_mpeg2_new(display, decoder_caps);
             break;
+        case GST_VAAPI_CODEC_VC1:
+            decoder = gst_vaapi_decoder_vc1_new(display, decoder_caps);
+            break;
         default:
             decoder = NULL;
             break;