decoder: mpeg4: fix picture decoder return value for skipped frames.
[platform/upstream/gstreamer-vaapi.git] / gst-libs / gst / vaapi / gstvaapidecoder_mpeg4.c
1 /*
2  *  gstvaapidecoder_mpeg4.c - MPEG-4 decoder
3  *
4  *  Copyright (C) 2011-2013 Intel Corporation
5  *    Author: Halley Zhao <halley.zhao@intel.com>
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser General Public License
9  *  as published by the Free Software Foundation; either version 2.1
10  *  of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free
19  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  *  Boston, MA 02110-1301 USA
21  */
22
23 /**
24  * SECTION:gstvaapidecoder_mpeg4
25  * @short_description: MPEG-4 decoder, include h263/divx/xvid support
26  */
27
28 #include "sysdeps.h"
29 #include <string.h>
30 #include <gst/base/gstbitreader.h>
31 #include <gst/codecparsers/gstmpeg4parser.h>
32 #include "gstvaapidecoder_mpeg4.h"
33 #include "gstvaapidecoder_objects.h"
34 #include "gstvaapidecoder_priv.h"
35 #include "gstvaapidisplay_priv.h"
36 #include "gstvaapiobject_priv.h"
37
38 #define DEBUG 1
39 #include "gstvaapidebug.h"
40
41 #define GST_VAAPI_DECODER_MPEG4_CAST(decoder) \
42     ((GstVaapiDecoderMpeg4 *)(decoder))
43
44 typedef struct _GstVaapiDecoderMpeg4Private     GstVaapiDecoderMpeg4Private;
45 typedef struct _GstVaapiDecoderMpeg4Class       GstVaapiDecoderMpeg4Class;
46
47 struct _GstVaapiDecoderMpeg4Private {
48     GstVaapiProfile                 profile;
49     guint                           level; 
50     guint                           width; 
51     guint                           height;
52     guint                           fps_n;
53     guint                           fps_d; 
54     guint                           coding_type;
55     GstMpeg4VisualObjectSequence    vos_hdr;
56     GstMpeg4VisualObject            vo_hdr;
57     GstMpeg4VideoSignalType         signal_type;
58     GstMpeg4VideoObjectLayer        vol_hdr;
59     GstMpeg4VideoObjectPlane        vop_hdr;
60     GstMpeg4VideoPlaneShortHdr      svh_hdr;
61     GstMpeg4VideoPacketHdr          packet_hdr;
62     GstMpeg4SpriteTrajectory        sprite_trajectory;
63     VAIQMatrixBufferMPEG4           iq_matrix;
64     GstVaapiPicture                *curr_picture;
65     // forward reference pic
66     GstVaapiPicture                *next_picture;
67     // backward reference pic
68     GstVaapiPicture                *prev_picture;
69     GstClockTime                    seq_pts;
70     GstClockTime                    gop_pts;
71     GstClockTime                    pts_diff;
72     GstClockTime                    max_pts;
73     // anchor sync time base for any picture type, 
74     // it is time base of backward reference frame
75     GstClockTime                    last_sync_time; 
76     // time base for recent I/P/S frame, 
77     // it is time base of forward reference frame for B frame
78     GstClockTime                    sync_time; 
79
80     /* last non-b-frame time by resolution */
81     GstClockTime                    last_non_b_scale_time;
82     GstClockTime                    non_b_scale_time;
83     GstClockTime                    trb;
84     GstClockTime                    trd;
85     // temporal_reference of previous frame of svh
86     guint8                          prev_t_ref;
87     guint                           is_opened               : 1;
88     guint                           is_first_field          : 1;
89     guint                           size_changed            : 1;
90     guint                           profile_changed         : 1;
91     guint                           progressive_sequence    : 1;
92     guint                           closed_gop              : 1;
93     guint                           broken_link             : 1;
94     guint                           calculate_pts_diff      : 1;
95     guint                           is_svh                  : 1;
96 };
97
98 /**
99  * GstVaapiDecoderMpeg4:
100  *
101  * A decoder based on Mpeg4.
102  */
103 struct _GstVaapiDecoderMpeg4 {
104     /*< private >*/
105     GstVaapiDecoder             parent_instance;
106     GstVaapiDecoderMpeg4Private priv;
107 };
108
109 /**
110  * GstVaapiDecoderMpeg4Class:
111  *
112  * A decoder class based on Mpeg4.
113  */
114 struct _GstVaapiDecoderMpeg4Class {
115     /*< private >*/
116     GstVaapiDecoderClass parent_class;
117 };
118
119 static void
120 gst_vaapi_decoder_mpeg4_close(GstVaapiDecoderMpeg4 *decoder)
121 {
122     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
123
124     gst_vaapi_picture_replace(&priv->curr_picture, NULL);
125     gst_vaapi_picture_replace(&priv->next_picture, NULL);
126     gst_vaapi_picture_replace(&priv->prev_picture, NULL);
127 }
128
129 static gboolean
130 gst_vaapi_decoder_mpeg4_open(GstVaapiDecoderMpeg4 *decoder)
131 {
132     GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER(decoder);
133     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
134     GstCaps *caps = NULL;
135     GstStructure *structure = NULL;
136
137     gst_vaapi_decoder_mpeg4_close(decoder);
138
139     priv->is_svh = 0;
140     caps = gst_vaapi_decoder_get_caps(base_decoder);
141     if (caps) {
142         structure = gst_caps_get_structure(caps, 0);
143         if (structure) {
144             if (gst_structure_has_name(structure, "video/x-h263")) {
145                 priv->is_svh = 1;
146                 priv->profile = GST_VAAPI_PROFILE_MPEG4_SIMPLE;
147                 priv->prev_t_ref = -1;
148             }
149         }
150     }
151     return TRUE;
152 }
153
154 static void
155 gst_vaapi_decoder_mpeg4_destroy(GstVaapiDecoder *base_decoder)
156 {
157     GstVaapiDecoderMpeg4 * const decoder =
158         GST_VAAPI_DECODER_MPEG4_CAST(base_decoder);
159
160     gst_vaapi_decoder_mpeg4_close(decoder);
161 }
162
163 static gboolean
164 gst_vaapi_decoder_mpeg4_create(GstVaapiDecoder *base_decoder)
165 {
166     GstVaapiDecoderMpeg4 * const decoder =
167         GST_VAAPI_DECODER_MPEG4_CAST(base_decoder);
168     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
169
170     priv->profile               = GST_VAAPI_PROFILE_MPEG4_SIMPLE;
171     priv->seq_pts               = GST_CLOCK_TIME_NONE;
172     priv->gop_pts               = GST_CLOCK_TIME_NONE;
173     priv->max_pts               = GST_CLOCK_TIME_NONE;
174     priv->calculate_pts_diff    = TRUE;
175     priv->size_changed          = TRUE;
176     priv->profile_changed       = TRUE;
177     return TRUE;
178 }
179
180 static inline void
181 copy_quant_matrix(guint8 dst[64], const guint8 src[64])
182 {
183     memcpy(dst, src, 64);
184 }
185
186 static GstVaapiDecoderStatus
187 ensure_context(GstVaapiDecoderMpeg4 *decoder)
188 {
189     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
190     GstVaapiProfile profiles[2];
191     GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
192     guint i, n_profiles = 0;
193     gboolean reset_context = FALSE;
194
195     if (priv->profile_changed) {
196         GST_DEBUG("profile changed");
197         priv->profile_changed = FALSE;
198         reset_context         = TRUE;
199
200         profiles[n_profiles++] = priv->profile;
201         if (priv->profile == GST_VAAPI_PROFILE_MPEG4_SIMPLE)
202             profiles[n_profiles++] = GST_VAAPI_PROFILE_MPEG4_ADVANCED_SIMPLE;
203
204         for (i = 0; i < n_profiles; i++) {
205             if (gst_vaapi_display_has_decoder(GST_VAAPI_DECODER_DISPLAY(decoder),
206                                               profiles[i], entrypoint))
207                 break;
208         }
209         if (i == n_profiles)
210             return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
211         priv->profile = profiles[i];
212     }
213
214     if (priv->size_changed) {
215         GST_DEBUG("size changed");
216         priv->size_changed = FALSE;
217         reset_context      = TRUE;
218     }
219
220     if (reset_context) {
221         GstVaapiContextInfo info;
222
223         info.profile    = priv->profile;
224         info.entrypoint = entrypoint;
225         info.chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
226         info.width      = priv->width;
227         info.height     = priv->height;
228         info.ref_frames = 2;
229         reset_context   = gst_vaapi_decoder_ensure_context(
230             GST_VAAPI_DECODER(decoder),
231             &info
232         );
233         if (!reset_context)
234             return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
235     }
236     return GST_VAAPI_DECODER_STATUS_SUCCESS;
237 }
238
239 static GstVaapiDecoderStatus
240 ensure_quant_matrix(GstVaapiDecoderMpeg4 *decoder, GstVaapiPicture *picture)
241 {
242     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
243     VAIQMatrixBufferMPEG4 *iq_matrix;
244
245     if (!priv->vol_hdr.load_intra_quant_mat && !priv->vol_hdr.load_non_intra_quant_mat) {
246             return GST_VAAPI_DECODER_STATUS_SUCCESS;
247     }
248
249     picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(MPEG4, decoder);
250     if (!picture->iq_matrix) {
251         GST_DEBUG("failed to allocate IQ matrix");
252         return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
253     }
254     iq_matrix = picture->iq_matrix->param;
255
256     if (priv->vol_hdr.load_intra_quant_mat) {
257         iq_matrix->load_intra_quant_mat = 1;
258         copy_quant_matrix(iq_matrix->intra_quant_mat,
259                           priv->vol_hdr.intra_quant_mat);
260     }
261     else
262         iq_matrix->load_intra_quant_mat = 0;
263
264     if (priv->vol_hdr.load_non_intra_quant_mat) {
265         iq_matrix->load_non_intra_quant_mat = 1;
266         copy_quant_matrix(iq_matrix->non_intra_quant_mat,
267                       priv->vol_hdr.non_intra_quant_mat);
268     }
269     else
270         iq_matrix->load_non_intra_quant_mat = 0;
271     
272
273     return GST_VAAPI_DECODER_STATUS_SUCCESS;
274 }
275
276 static inline GstVaapiDecoderStatus
277 render_picture(GstVaapiDecoderMpeg4 *decoder, GstVaapiPicture *picture)
278 {
279     if (!gst_vaapi_picture_output(picture))
280         return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
281     return GST_VAAPI_DECODER_STATUS_SUCCESS;
282 }
283
284 /* decode_picture() start to decode a frame/picture
285  * decode_current_picture() finishe decoding a frame/picture 
286  * (commit buffer to driver for decoding)
287  */
288 static GstVaapiDecoderStatus
289 decode_current_picture(GstVaapiDecoderMpeg4 *decoder)
290 {
291     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
292     GstVaapiPicture * const picture = priv->curr_picture;
293     GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_SUCCESS;
294
295     if (picture) {
296         if (!gst_vaapi_picture_decode(picture))
297             status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
298         if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture)) {
299             if ((priv->prev_picture && priv->next_picture) ||
300                 (priv->closed_gop && priv->next_picture))
301                 status = render_picture(decoder, picture);
302         }
303         gst_vaapi_picture_replace(&priv->curr_picture, NULL);
304     }
305     return status;
306 }
307
308 static GstVaapiDecoderStatus
309 decode_sequence(GstVaapiDecoderMpeg4 *decoder, const guint8 *buf, guint buf_size)
310 {
311     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
312     GstMpeg4VisualObjectSequence * const vos_hdr = &priv->vos_hdr;
313     GstVaapiProfile profile;
314
315     if (gst_mpeg4_parse_visual_object_sequence(vos_hdr, buf, buf_size) != GST_MPEG4_PARSER_OK) {
316         GST_DEBUG("failed to parse sequence header");
317         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
318     }
319
320     priv->level = vos_hdr->level;
321     switch (vos_hdr->profile) {
322     case GST_MPEG4_PROFILE_SIMPLE:
323         profile = GST_VAAPI_PROFILE_MPEG4_SIMPLE;
324         break;
325     case GST_MPEG4_PROFILE_ADVANCED_SIMPLE:
326     case GST_MPEG4_PROFILE_SIMPLE_SCALABLE: /* shared profile with ADVANCED_SIMPLE */
327         profile = GST_VAAPI_PROFILE_MPEG4_ADVANCED_SIMPLE;
328         break;
329     default:
330         GST_DEBUG("unsupported profile %d", vos_hdr->profile);
331         return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
332     }
333     if (priv->profile != profile) {
334         priv->profile = profile;
335         priv->profile_changed = TRUE;
336     }
337     priv->seq_pts = GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts;
338     priv->size_changed          = TRUE;
339
340     return GST_VAAPI_DECODER_STATUS_SUCCESS;
341 }
342
343 static GstVaapiDecoderStatus
344 decode_sequence_end(GstVaapiDecoderMpeg4 *decoder)
345 {
346     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
347     GstVaapiDecoderStatus status;
348
349     if (priv->curr_picture) {
350         status = decode_current_picture(decoder);
351         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
352             return status;
353         status = render_picture(decoder, priv->curr_picture);
354         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
355             return status;
356     }
357
358     if (priv->next_picture) {
359         status = render_picture(decoder, priv->next_picture);
360         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
361             return status;
362     }
363     return GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
364 }
365
366 static GstVaapiDecoderStatus
367 decode_visual_object(GstVaapiDecoderMpeg4 *decoder, const guint8 *buf, guint buf_size)
368 {
369     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
370     GstMpeg4VisualObject * vo_hdr = &priv->vo_hdr;
371     GstMpeg4VideoSignalType * signal_type = &priv->signal_type;
372
373     if (gst_mpeg4_parse_visual_object (vo_hdr, signal_type, buf, buf_size) != GST_MPEG4_PARSER_OK) {
374         GST_DEBUG("failed to parse visual object");
375         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
376     }
377
378     /* XXX: video_signal_type isn't used for decoding */
379     return GST_VAAPI_DECODER_STATUS_SUCCESS;
380 }
381
382 static GstVaapiDecoderStatus
383 decode_video_object_layer(GstVaapiDecoderMpeg4 *decoder, const guint8 *buf, guint buf_size)
384 {
385     GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
386     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
387     GstMpeg4VisualObject * vo_hdr = &priv->vo_hdr;
388     GstMpeg4VideoObjectLayer * vol_hdr = &priv->vol_hdr;
389
390     if (gst_mpeg4_parse_video_object_layer (vol_hdr, vo_hdr, buf, buf_size) != GST_MPEG4_PARSER_OK) {
391         GST_DEBUG("failed to parse video object layer");
392         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
393     }
394
395     priv->width  = vol_hdr->width;
396     priv->height = vol_hdr->height;
397
398     priv->progressive_sequence  = !vol_hdr->interlaced;
399
400     if (vol_hdr->fixed_vop_rate) {
401         priv->fps_n = vol_hdr->vop_time_increment_resolution;
402         priv->fps_d = vol_hdr->fixed_vop_time_increment;
403         gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);    
404     }
405
406     gst_vaapi_decoder_set_pixel_aspect_ratio(base_decoder, priv->vol_hdr.par_width, priv->vol_hdr.par_height);
407     gst_vaapi_decoder_set_picture_size(base_decoder, priv->width, priv->height);
408
409     return GST_VAAPI_DECODER_STATUS_SUCCESS;
410 }
411
412 static GstVaapiDecoderStatus
413 decode_gop(GstVaapiDecoderMpeg4 *decoder, const guint8 *buf, guint buf_size)
414 {
415     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
416     GstMpeg4GroupOfVOP gop;
417     GstClockTime gop_time;
418
419     if (buf_size >4) {
420         if (gst_mpeg4_parse_group_of_vop(&gop, buf, buf_size) != GST_MPEG4_PARSER_OK) {
421         GST_DEBUG("failed to parse GOP");
422         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
423         }
424     }
425     else {
426         gop.closed          = 1;
427         gop.broken_link     = 0;
428         gop.hours           = 0;
429         gop.minutes         = 0;
430         gop.seconds         = 0;
431     }
432
433     priv->closed_gop  = gop.closed;
434     priv->broken_link = gop.broken_link;
435
436     GST_DEBUG("GOP %02u:%02u:%02u (closed_gop %d, broken_link %d)",
437               gop.hours, gop.minutes, gop.seconds,
438               priv->closed_gop, priv->broken_link);
439
440     gop_time             = gop.hours * 3600 + gop.minutes * 60 + gop.seconds;
441     priv->last_sync_time = gop_time;
442     priv->sync_time      = gop_time;
443     
444     if (priv->gop_pts != GST_CLOCK_TIME_NONE)
445         priv->pts_diff += gop_time * GST_SECOND - priv->gop_pts;
446     priv->gop_pts = gop_time * GST_SECOND;
447     priv->calculate_pts_diff = TRUE;
448     priv->is_first_field = TRUE;
449
450     return GST_VAAPI_DECODER_STATUS_SUCCESS;
451 }
452
453 void
454 calculate_pts_diff(GstVaapiDecoderMpeg4 *decoder,
455                       GstMpeg4VideoObjectLayer *vol_hdr,
456                       GstMpeg4VideoObjectPlane *vop_hdr)
457 {
458     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
459     GstClockTime frame_timestamp;
460
461     frame_timestamp = GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts;
462     if (frame_timestamp && frame_timestamp != GST_CLOCK_TIME_NONE) {
463         /* Buffer with timestamp */
464         if (priv->max_pts != GST_CLOCK_TIME_NONE &&
465             frame_timestamp < priv->max_pts) {
466             frame_timestamp = priv->max_pts +
467                 gst_util_uint64_scale((vol_hdr->fixed_vop_rate ?
468                                        vol_hdr->fixed_vop_time_increment : 1),
469                                       GST_SECOND,
470                                       vol_hdr->vop_time_increment_resolution);
471         }
472     } else {
473         /* Buffer without timestamp set */
474         if (priv->max_pts == GST_CLOCK_TIME_NONE) /* first buffer */
475             frame_timestamp = 0;
476         else {
477             GstClockTime tmp_pts;
478             tmp_pts = priv->pts_diff + priv->gop_pts +
479                 vop_hdr->modulo_time_base * GST_SECOND +
480                 gst_util_uint64_scale(vop_hdr->time_increment,
481                                       GST_SECOND,
482                                       vol_hdr->vop_time_increment_resolution);
483             if (tmp_pts > priv->max_pts)
484                 frame_timestamp = tmp_pts;
485             else
486                 frame_timestamp = priv->max_pts +
487                     gst_util_uint64_scale((vol_hdr->fixed_vop_rate ?
488                                            vol_hdr->fixed_vop_time_increment : 1),
489                                            GST_SECOND,
490                                           vol_hdr->vop_time_increment_resolution);
491         }
492     }
493
494     priv->pts_diff = frame_timestamp -
495         (priv->gop_pts + vop_hdr->modulo_time_base * GST_SECOND +
496          gst_util_uint64_scale(vop_hdr->time_increment, GST_SECOND,
497                                vol_hdr->vop_time_increment_resolution));
498 }
499  
500 static GstVaapiDecoderStatus
501 decode_picture(GstVaapiDecoderMpeg4 *decoder, const guint8 *buf, guint buf_size)
502 {
503     GstMpeg4ParseResult parser_result = GST_MPEG4_PARSER_OK;
504     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
505     GstMpeg4VideoObjectPlane * const vop_hdr = &priv->vop_hdr;
506     GstMpeg4VideoObjectLayer * const vol_hdr = &priv->vol_hdr;
507     GstMpeg4SpriteTrajectory * const sprite_trajectory = &priv->sprite_trajectory;
508     GstVaapiPicture *picture;
509     GstVaapiDecoderStatus status;
510     GstClockTime pts;
511
512     // context depends on priv->width and priv->height, so we move parse_vop a little earlier
513     if (priv->is_svh) {
514         parser_result = gst_mpeg4_parse_video_plane_short_header(&priv->svh_hdr, buf, buf_size);
515
516     }
517     else {
518         parser_result = gst_mpeg4_parse_video_object_plane(vop_hdr, sprite_trajectory, vol_hdr, buf, buf_size);
519         /* Need to skip this frame if VOP was not coded */
520         if (GST_MPEG4_PARSER_OK == parser_result && !vop_hdr->coded)
521             return GST_VAAPI_DECODER_STATUS_DROP_FRAME;
522     }
523
524     if (parser_result != GST_MPEG4_PARSER_OK) {
525         GST_DEBUG("failed to parse picture header");
526         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
527     }
528
529     if (priv->is_svh) {
530         priv->width = priv->svh_hdr.vop_width;
531         priv->height = priv->svh_hdr.vop_height;
532     }
533     else {
534         if (!vop_hdr->width && !vop_hdr->height) {
535             vop_hdr->width = vol_hdr->width;
536             vop_hdr->height = vol_hdr->height;
537         }
538         priv->width = vop_hdr->width;
539         priv->height = vop_hdr->height;
540     }
541
542     status = ensure_context(decoder);
543     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
544         GST_DEBUG("failed to reset context");
545         return status;
546     }
547
548     if (priv->curr_picture) {
549         status = decode_current_picture(decoder);
550         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
551             return status;
552     }
553
554     priv->curr_picture = GST_VAAPI_PICTURE_NEW(MPEG4, decoder);
555     if (!priv->curr_picture) {
556         GST_DEBUG("failed to allocate picture");
557         return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
558     }
559     picture = priv->curr_picture;
560
561     status = ensure_quant_matrix(decoder, picture);
562     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
563         GST_DEBUG("failed to reset quantizer matrix");
564         return status;
565     }
566
567     /* 7.6.7 Temporal prediction structure
568      * forward reference frame     B B B B B B      backward reference frame
569      *            |                                              |
570      *  nearest I/P/S in the past with vop_coded ==1             |
571      *                         nearest I/P/S in the future with any vop_coded
572      * fixme, it said that B frame shouldn't use backward reference frame 
573      *        when backward reference frame coded is 0
574      */
575     if (priv->is_svh) {
576         priv->coding_type = priv->svh_hdr.picture_coding_type;
577     }
578     else {
579         priv->coding_type = priv->vop_hdr.coding_type;
580     }
581     switch (priv->coding_type) {
582     case GST_MPEG4_I_VOP:
583         picture->type = GST_VAAPI_PICTURE_TYPE_I;
584         if (priv->is_svh || vop_hdr->coded) 
585             GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
586         break;
587     case GST_MPEG4_P_VOP:
588         picture->type = GST_VAAPI_PICTURE_TYPE_P;
589         if (priv->is_svh || vop_hdr->coded) 
590             GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
591         break;
592     case GST_MPEG4_B_VOP:
593         picture->type = GST_VAAPI_PICTURE_TYPE_B;
594         break;
595     case GST_MPEG4_S_VOP:
596         picture->type = GST_VAAPI_PICTURE_TYPE_S;
597         // see 3.175 reference VOP
598         if (vop_hdr->coded) 
599             GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
600         break;
601     default:
602         GST_DEBUG("unsupported picture type %d", priv->coding_type);
603         return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
604     }
605
606     if (!priv->is_svh && !vop_hdr->coded) {
607         status = render_picture(decoder, priv->prev_picture);
608         return status;
609     }
610
611     if (priv->is_svh) {
612         guint temp_ref = priv->svh_hdr.temporal_reference;
613         if (temp_ref < priv->prev_t_ref) {
614             temp_ref += 256;
615         }
616         guint delta_ref = temp_ref - priv->prev_t_ref;
617
618         pts = priv->sync_time;
619         // see temporal_reference definition in spec, 30000/1001Hz
620         pts += gst_util_uint64_scale(delta_ref, GST_SECOND*1001, 30000);
621         priv->sync_time = pts;
622         priv->prev_t_ref = priv->svh_hdr.temporal_reference;
623     }
624     else {
625         /* Update priv->pts_diff */
626         if (priv->calculate_pts_diff) {
627             calculate_pts_diff(decoder, vol_hdr, vop_hdr);
628             priv->calculate_pts_diff = FALSE;
629         }
630
631         /* Update presentation time, 6.3.5 */
632         if(vop_hdr->coding_type != GST_MPEG4_B_VOP) {
633             // increment basing on decoding order
634             priv->last_sync_time = priv->sync_time;
635             priv->sync_time = priv->last_sync_time + vop_hdr->modulo_time_base;
636             pts = priv->sync_time * GST_SECOND;
637             pts += gst_util_uint64_scale(vop_hdr->time_increment, GST_SECOND, vol_hdr->vop_time_increment_resolution);
638             priv->last_non_b_scale_time = priv->non_b_scale_time;
639             priv->non_b_scale_time = priv->sync_time * vol_hdr->vop_time_increment_resolution + vop_hdr->time_increment;
640             priv->trd  = priv->non_b_scale_time - priv->last_non_b_scale_time;
641         }
642         else {
643             // increment basing on display oder
644             pts = (priv->last_sync_time + vop_hdr->modulo_time_base) * GST_SECOND;
645             pts += gst_util_uint64_scale(vop_hdr->time_increment, GST_SECOND, vol_hdr->vop_time_increment_resolution);
646             priv->trb = (priv->last_sync_time + vop_hdr->modulo_time_base) * vol_hdr->vop_time_increment_resolution +
647                 vop_hdr->time_increment - priv->last_non_b_scale_time;
648         }
649     }
650     picture->pts = pts + priv->pts_diff;
651     if (priv->max_pts == GST_CLOCK_TIME_NONE || priv->max_pts < picture->pts)
652         priv->max_pts = picture->pts;
653
654     /* Update reference pictures */
655     /* XXX: consider priv->vol_hdr.low_delay, consider packed video frames for DivX/XviD */
656     if (GST_VAAPI_PICTURE_IS_REFERENCE(picture)) {
657         if (priv->next_picture)
658             status = render_picture(decoder, priv->next_picture);
659         gst_vaapi_picture_replace(&priv->prev_picture, priv->next_picture);
660         gst_vaapi_picture_replace(&priv->next_picture, picture);
661     }
662     return status;
663 }
664
665 static inline guint
666 get_vop_coding_type(GstVaapiPicture *picture)
667 {
668     return picture->type - GST_VAAPI_PICTURE_TYPE_I;
669 }
670
671 static gboolean
672 fill_picture(GstVaapiDecoderMpeg4 *decoder, GstVaapiPicture *picture)
673 {
674     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
675     VAPictureParameterBufferMPEG4 * const pic_param = picture->param;
676     GstMpeg4VideoObjectPlane * const vop_hdr = &priv->vop_hdr;
677
678     /* Fill in VAPictureParameterBufferMPEG4 */
679     pic_param->forward_reference_picture                        = VA_INVALID_ID;
680     pic_param->backward_reference_picture                       = VA_INVALID_ID;
681
682     pic_param->vol_fields.value                                 = 0;
683     pic_param->vop_fields.value                                 = 0;
684     if(priv->is_svh) {
685         // vol_hdr Parameters
686         pic_param->vol_fields.bits.short_video_header           = 1; 
687         // does the following vol_hdr parameters matter for short video header?
688         pic_param->vol_fields.bits.chroma_format                = 1; // I420, see table 6-15. 
689         pic_param->vol_fields.bits.interlaced                   = 0; 
690         pic_param->vol_fields.bits.obmc_disable                 = 1;
691         pic_param->vol_fields.bits.sprite_enable                = 0;
692         pic_param->vol_fields.bits.sprite_warping_accuracy      = 0;
693         pic_param->vol_fields.bits.quant_type                   = 0; //method 1; $7.4.4
694         pic_param->vol_fields.bits.quarter_sample               = 0; 
695         pic_param->vol_fields.bits.data_partitioned             = 0; 
696         pic_param->vol_fields.bits.reversible_vlc               = 0; 
697         pic_param->vol_fields.bits.resync_marker_disable        = 1; 
698         pic_param->no_of_sprite_warping_points                  = 0; 
699         pic_param->quant_precision                              = 5;
700         // VOP parameters    
701         pic_param->vop_width                                    = priv->svh_hdr.vop_width;
702         pic_param->vop_height                                   = priv->svh_hdr.vop_height;
703         pic_param->vop_fields.bits.vop_coding_type              = priv->svh_hdr.picture_coding_type;
704         pic_param->vop_time_increment_resolution                = priv->vol_hdr.vop_time_increment_resolution; 
705         
706         pic_param->num_gobs_in_vop                              = priv->svh_hdr.num_gobs_in_vop;
707         pic_param->num_macroblocks_in_gob                       = priv->svh_hdr.num_macroblocks_in_gob;
708     }
709     else {
710         // VOL parameters
711         pic_param->vol_fields.bits.short_video_header           = 0; 
712         pic_param->vol_fields.bits.chroma_format                = priv->vol_hdr.chroma_format;
713         pic_param->vol_fields.bits.interlaced                   = priv->vol_hdr.interlaced;
714         pic_param->vol_fields.bits.obmc_disable                 = priv->vol_hdr.obmc_disable;
715         pic_param->vol_fields.bits.sprite_enable                = priv->vol_hdr.sprite_enable;
716         pic_param->vol_fields.bits.sprite_warping_accuracy      = priv->vol_hdr.sprite_warping_accuracy; 
717         pic_param->vol_fields.bits.quant_type                   = priv->vol_hdr.quant_type;
718         pic_param->vol_fields.bits.quarter_sample               = priv->vol_hdr.quarter_sample;
719         pic_param->vol_fields.bits.data_partitioned             = priv->vol_hdr.data_partitioned;
720         pic_param->vol_fields.bits.reversible_vlc               = priv->vol_hdr.reversible_vlc;
721         pic_param->vol_fields.bits.resync_marker_disable        = priv->vol_hdr.resync_marker_disable;
722         pic_param->no_of_sprite_warping_points                  = priv->vol_hdr.no_of_sprite_warping_points;
723         int i =0;
724         for (i=0; i<3 && i<priv->vol_hdr.no_of_sprite_warping_points ; i++) {
725             pic_param->sprite_trajectory_du[i]                  = priv->sprite_trajectory.vop_ref_points[i];
726             pic_param->sprite_trajectory_dv[i]                  = priv->sprite_trajectory.sprite_ref_points[i];
727         }
728         pic_param->quant_precision                              = priv->vol_hdr.quant_precision;
729         
730         // VOP parameters    
731         pic_param->vop_width                                    = vop_hdr->width;
732         pic_param->vop_height                                   = vop_hdr->height;
733         pic_param->vop_fields.bits.vop_coding_type              = vop_hdr->coding_type;
734         pic_param->vop_fields.bits.vop_rounding_type            = vop_hdr->rounding_type;
735         pic_param->vop_fields.bits.intra_dc_vlc_thr             = vop_hdr->intra_dc_vlc_thr;
736         pic_param->vop_fields.bits.top_field_first              = vop_hdr->top_field_first;
737         pic_param->vop_fields.bits.alternate_vertical_scan_flag = vop_hdr->alternate_vertical_scan_flag;
738
739         pic_param->vop_fcode_forward                            = vop_hdr->fcode_forward;
740         pic_param->vop_fcode_backward                           = vop_hdr->fcode_backward;
741         pic_param->vop_time_increment_resolution                = priv->vol_hdr.vop_time_increment_resolution;
742     }    
743
744     pic_param->TRB = 0;
745     pic_param->TRD = 0;
746     switch (priv->coding_type) {
747     case GST_MPEG4_B_VOP:
748         pic_param->TRB                                          = priv->trb;
749         pic_param->backward_reference_picture                   = priv->next_picture->surface_id;
750         pic_param->vop_fields.bits.backward_reference_vop_coding_type = get_vop_coding_type(priv->next_picture);
751         // fall-through
752     case GST_MPEG4_P_VOP:
753         pic_param->TRD                                          = priv->trd;
754         if (priv->prev_picture)
755             pic_param->forward_reference_picture                = priv->prev_picture->surface_id;
756         break;
757     }
758
759     if (priv->vol_hdr.interlaced) {
760         priv->is_first_field ^= 1;
761     }
762     return TRUE;
763 }
764
765 static GstVaapiDecoderStatus
766 decode_slice(
767     GstVaapiDecoderMpeg4 *decoder,
768     const guint8          *buf,
769     guint                 buf_size,
770     gboolean              has_packet_header
771 )
772 {
773     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
774     GstVaapiPicture * const picture = priv->curr_picture;
775     GstVaapiSlice *slice;
776     VASliceParameterBufferMPEG4 *slice_param;
777
778     GST_DEBUG("decoder silce: %p, %u bytes)", buf, buf_size);
779
780     // has_packet_header is ture for the 2+ slice
781     if (!has_packet_header && !fill_picture(decoder, picture))
782         return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
783
784     slice = GST_VAAPI_SLICE_NEW(MPEG4, decoder, buf, buf_size);
785     if (!slice) {
786         GST_DEBUG("failed to allocate slice");
787         return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
788     }
789     gst_vaapi_picture_add_slice(picture, slice);
790
791     /* Fill in VASliceParameterBufferMPEG4 */
792     slice_param = slice->param;
793     if (priv->is_svh) {
794         slice_param->macroblock_offset         = (priv->svh_hdr.size)%8;
795         slice_param->macroblock_number         = 0; 
796         // the header of first gob_layer is empty (gob_header_empty=1), use vop_quant
797         slice_param->quant_scale               = priv->svh_hdr.vop_quant; 
798     }
799     else {
800         if (has_packet_header) {
801             slice_param->macroblock_offset     = priv->packet_hdr.size % 8;
802             slice_param->macroblock_number     = priv->packet_hdr.macroblock_number;
803             slice_param->quant_scale           = priv->packet_hdr.quant_scale;
804        }    
805         else {
806             slice_param->macroblock_offset     = priv->vop_hdr.size % 8;
807             slice_param->macroblock_number     = 0;
808             slice_param->quant_scale           = priv->vop_hdr.quant;
809         }
810     }
811     return GST_VAAPI_DECODER_STATUS_SUCCESS;
812 }
813
814 static GstVaapiDecoderStatus
815 decode_packet(GstVaapiDecoderMpeg4 *decoder, GstMpeg4Packet packet)
816 {
817     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
818     GstMpeg4Packet *tos = &packet;
819     GstVaapiDecoderStatus status;
820
821     if (tos->size < 0)
822         return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
823
824     // packet.size is the size from current marker to the next.
825     if (tos->type == GST_MPEG4_VISUAL_OBJ_SEQ_START) {
826         status = decode_sequence(decoder, packet.data + packet.offset, packet.size);
827     }
828     else if (tos->type == GST_MPEG4_VISUAL_OBJ_SEQ_END) {
829         status = decode_sequence_end(decoder);
830     }
831     else if (tos->type == GST_MPEG4_VISUAL_OBJ) {
832         status = decode_visual_object(decoder, packet.data + packet.offset, packet.size);
833     }
834     else if (tos->type >= GST_MPEG4_VIDEO_OBJ_FIRST && tos->type <= GST_MPEG4_VIDEO_OBJ_LAST) {
835         GST_WARNING("unexpected marker: (GST_MPEG4_VIDEO_OBJ_FIRST, GST_MPEG4_VIDEO_OBJ_LAST)");
836         status = GST_VAAPI_DECODER_STATUS_SUCCESS;
837     }
838     else if (tos->type >= GST_MPEG4_VIDEO_LAYER_FIRST && tos->type <= GST_MPEG4_VIDEO_LAYER_LAST) {
839         status = decode_video_object_layer(decoder, packet.data + packet.offset, packet.size);
840     }
841     else if (tos->type == GST_MPEG4_GROUP_OF_VOP) {
842         status = decode_gop(decoder, packet.data + packet.offset, packet.size);
843     }
844     else if (tos->type == GST_MPEG4_VIDEO_OBJ_PLANE) {
845         status = decode_picture(decoder, packet.data + packet.offset, packet.size);
846         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
847             return status;
848
849         /* decode slice
850          * A resync marker shall only be located immediately before a macroblock 
851          * (or video packet header if exists) and aligned with a byte
852          * either start_code or resync_marker are scaned/measured by byte, 
853          * while the header itself are parsed/measured in bit
854          * it means: resync_marker(video_packet_header) start from byte boundary, 
855          * while MB doesn't start from byte boundary -- it is what 'macroblock_offset' 
856          * in slice refer to
857          */
858         const guint8 *_data = packet.data + packet.offset + priv->vop_hdr.size/8; 
859         gint  _data_size = packet.size - (priv->vop_hdr.size/8); 
860         GstMpeg4Packet video_packet;
861         
862         if (priv->vol_hdr.resync_marker_disable) {
863             status = decode_slice(decoder, _data, _data_size, FALSE);
864             if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
865                 return status;
866         }
867         else {
868             // next start_code is required to determine the end of last slice
869             _data_size += 4;
870             GstMpeg4ParseResult ret = GST_MPEG4_PARSER_OK;
871
872             gboolean first_slice = TRUE;
873             while (_data_size > 0) {
874                 // we can skip user data here
875                 ret = gst_mpeg4_parse(&video_packet, TRUE, &priv->vop_hdr, _data, 0,  _data_size);
876                 if(ret != GST_MPEG4_PARSER_OK) {
877                     break;
878                 }
879
880                 if (first_slice) {
881                     status = decode_slice(decoder, _data, video_packet.size, FALSE);
882                     first_slice = FALSE;
883                 }
884                 else {
885                     _data += video_packet.offset;
886                     _data_size -= video_packet.offset;
887
888                     ret = gst_mpeg4_parse_video_packet_header (&priv->packet_hdr, &priv->vol_hdr, &priv->vop_hdr, &priv->sprite_trajectory, _data, _data_size);
889                     status = decode_slice(decoder,_data + priv->packet_hdr.size/8, video_packet.size - priv->packet_hdr.size/8, TRUE); 
890                 }
891
892                 _data += video_packet.size;
893                 _data_size -= video_packet.size;
894             }
895         }
896         status = decode_current_picture(decoder);
897     }
898     else if (tos->type == GST_MPEG4_USER_DATA
899           || tos->type == GST_MPEG4_VIDEO_SESSION_ERR 
900           || tos->type == GST_MPEG4_FBA 
901           || tos->type == GST_MPEG4_FBA_PLAN 
902           || tos->type == GST_MPEG4_MESH 
903           || tos->type == GST_MPEG4_MESH_PLAN 
904           || tos->type == GST_MPEG4_STILL_TEXTURE_OBJ 
905           || tos->type == GST_MPEG4_TEXTURE_SPATIAL 
906           || tos->type == GST_MPEG4_TEXTURE_SNR_LAYER 
907           || tos->type == GST_MPEG4_TEXTURE_TILE 
908           || tos->type == GST_MPEG4_SHAPE_LAYER 
909           || tos->type == GST_MPEG4_STUFFING 
910           || tos->type == GST_MPEG4_SYSTEM_FIRST 
911           || tos->type == GST_MPEG4_SYSTEM_LAST) {
912         GST_WARNING("Ignore marker: %x\n", tos->type);
913         status = GST_VAAPI_DECODER_STATUS_SUCCESS;
914     }
915     else {
916         GST_ERROR("unsupported start code %x\n", tos->type);
917         status = GST_VAAPI_DECODER_STATUS_SUCCESS;
918     }
919     
920     return status;
921 }
922
923 static GstVaapiDecoderStatus
924 decode_buffer(GstVaapiDecoderMpeg4 *decoder, const guchar *buf, guint buf_size)
925 {
926     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
927     GstVaapiDecoderStatus status;
928     GstMpeg4Packet packet;
929     guint ofs;
930
931     if (priv->is_svh) {
932         status = decode_picture(decoder, buf, buf_size);
933         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
934             return status;
935
936         ofs = priv->svh_hdr.size / 8;
937         status = decode_slice(decoder, buf + ofs, buf_size - ofs, FALSE);
938         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
939             return status;
940     }
941     else {
942         packet.data   = buf;
943         packet.offset = 0;
944         packet.size   = buf_size;
945         packet.type   = (GstMpeg4StartCode)packet.data[0];
946
947         status = decode_packet(decoder, packet);
948         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
949             return status;
950     }
951     return GST_VAAPI_DECODER_STATUS_SUCCESS;
952 }
953
954 static GstVaapiDecoderStatus
955 gst_vaapi_decoder_mpeg4_decode_codec_data(GstVaapiDecoder *base_decoder,
956     const guchar *_buf, guint _buf_size)
957 {
958     GstVaapiDecoderMpeg4 * const decoder =
959         GST_VAAPI_DECODER_MPEG4_CAST(base_decoder);
960     GstVaapiDecoderStatus status;
961     guchar *buf;
962     guint pos, buf_size;
963
964     // add additional 0x000001b2 to enclose the last header
965     buf_size = _buf_size + 4;
966     buf = malloc(buf_size);
967     memcpy(buf, _buf, buf_size);
968     buf[buf_size-4] = 0;
969     buf[buf_size-3] = 0;
970     buf[buf_size-2] = 1;
971     buf[buf_size-1] = 0xb2;
972
973     pos = 0;
974     GstMpeg4Packet packet;
975     GstMpeg4ParseResult result = GST_MPEG4_PARSER_OK;
976
977     while (result == GST_MPEG4_PARSER_OK && pos < buf_size) {
978         result = gst_mpeg4_parse(&packet, FALSE, NULL, buf, pos, buf_size);
979         if (result != GST_MPEG4_PARSER_OK) {
980             break;
981         }
982         status = decode_packet(decoder, packet);
983         if (GST_VAAPI_DECODER_STATUS_SUCCESS == status) {
984             pos = packet.offset + packet.size; 
985         }
986         else {
987             GST_WARNING("decode mp4 packet failed when decoding codec data\n");
988             break;
989         }
990     }
991     free(buf);
992     return status;
993 }
994
995 static GstVaapiDecoderStatus
996 ensure_decoder(GstVaapiDecoderMpeg4 *decoder)
997 {
998     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
999     GstVaapiDecoderStatus status;
1000
1001     if (!priv->is_opened) {
1002         priv->is_opened = gst_vaapi_decoder_mpeg4_open(decoder);
1003         if (!priv->is_opened)
1004             return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
1005
1006         status = gst_vaapi_decoder_decode_codec_data(
1007             GST_VAAPI_DECODER_CAST(decoder));
1008         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1009             return status;
1010     }
1011     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1012 }
1013
1014 static GstVaapiDecoderStatus
1015 gst_vaapi_decoder_mpeg4_parse(GstVaapiDecoder *base_decoder,
1016     GstAdapter *adapter, gboolean at_eos, GstVaapiDecoderUnit *unit)
1017 {
1018     GstVaapiDecoderMpeg4 * const decoder =
1019         GST_VAAPI_DECODER_MPEG4_CAST(base_decoder);
1020     GstVaapiDecoderMpeg4Private * const priv = &decoder->priv;
1021     GstVaapiDecoderStatus status;
1022     GstMpeg4Packet packet;
1023     GstMpeg4ParseResult result;
1024     const guchar *buf;
1025     guint size, buf_size, flags = 0;
1026
1027     status = ensure_decoder(decoder);
1028     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1029         return status;
1030
1031     size = gst_adapter_available(adapter);
1032     buf = gst_adapter_map(adapter, size);
1033     if (!buf)
1034         return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1035
1036     if (priv->is_svh)
1037         result = gst_h263_parse(&packet, buf, 0, size);
1038     else
1039         result = gst_mpeg4_parse(&packet, FALSE, NULL, buf, 0, size);
1040     if (result == GST_MPEG4_PARSER_NO_PACKET_END && at_eos)
1041         packet.size = size - packet.offset;
1042     else if (result == GST_MPEG4_PARSER_ERROR)
1043         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1044     else if (result != GST_MPEG4_PARSER_OK)
1045         return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1046
1047     buf_size = packet.size;
1048     gst_adapter_flush(adapter, packet.offset);
1049     unit->size = buf_size;
1050
1051     /* Check for start of new picture */
1052     switch (packet.type) {
1053     case GST_MPEG4_VIDEO_SESSION_ERR:
1054     case GST_MPEG4_FBA:
1055     case GST_MPEG4_FBA_PLAN:
1056     case GST_MPEG4_MESH:
1057     case GST_MPEG4_MESH_PLAN:
1058     case GST_MPEG4_STILL_TEXTURE_OBJ:
1059     case GST_MPEG4_TEXTURE_SPATIAL:
1060     case GST_MPEG4_TEXTURE_SNR_LAYER:
1061     case GST_MPEG4_TEXTURE_TILE:
1062     case GST_MPEG4_SHAPE_LAYER:
1063     case GST_MPEG4_STUFFING:
1064         gst_adapter_flush(adapter, packet.size);
1065         return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1066     case GST_MPEG4_USER_DATA:
1067         flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1068         break;
1069     case GST_MPEG4_VISUAL_OBJ_SEQ_END:
1070         flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1071         flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
1072         break;
1073     case GST_MPEG4_VIDEO_OBJ_PLANE:
1074         flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
1075         flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1076         /* fall-through */
1077     case GST_MPEG4_VISUAL_OBJ_SEQ_START:
1078     case GST_MPEG4_VISUAL_OBJ:
1079     case GST_MPEG4_GROUP_OF_VOP:
1080         flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
1081         break;
1082     default:
1083         if (packet.type >= GST_MPEG4_VIDEO_OBJ_FIRST &&
1084             packet.type <= GST_MPEG4_VIDEO_OBJ_LAST) {
1085             gst_adapter_flush(adapter, packet.size);
1086             return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1087         }
1088         if (packet.type >= GST_MPEG4_VIDEO_LAYER_FIRST &&
1089             packet.type <= GST_MPEG4_VIDEO_LAYER_LAST) {
1090             break;
1091         }
1092         if (packet.type >= GST_MPEG4_SYSTEM_FIRST &&
1093             packet.type <= GST_MPEG4_SYSTEM_LAST) {
1094             flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1095             break;
1096         }
1097         GST_WARNING("unsupported start code (0x%02x)", packet.type);
1098         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1099     }
1100     GST_VAAPI_DECODER_UNIT_FLAG_SET(unit, flags);
1101     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1102 }
1103
1104 static GstVaapiDecoderStatus
1105 gst_vaapi_decoder_mpeg4_decode(GstVaapiDecoder *base_decoder,
1106     GstVaapiDecoderUnit *unit)
1107 {
1108     GstVaapiDecoderMpeg4 * const decoder =
1109         GST_VAAPI_DECODER_MPEG4_CAST(base_decoder);
1110     GstVaapiDecoderStatus status;
1111     GstBuffer * const buffer =
1112         GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer;
1113     GstMapInfo map_info;
1114
1115     status = ensure_decoder(decoder);
1116     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1117         return status;
1118
1119     if (!gst_buffer_map(buffer, &map_info, GST_MAP_READ)) {
1120         GST_ERROR("failed to map buffer");
1121         return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1122     }
1123
1124     status = decode_buffer(decoder, map_info.data + unit->offset, unit->size);
1125     gst_buffer_unmap(buffer, &map_info);
1126     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1127         return status;
1128     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1129 }
1130
1131 static void
1132 gst_vaapi_decoder_mpeg4_class_init(GstVaapiDecoderMpeg4Class *klass)
1133 {
1134     GstVaapiMiniObjectClass * const object_class =
1135         GST_VAAPI_MINI_OBJECT_CLASS(klass);
1136     GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
1137
1138     object_class->size          = sizeof(GstVaapiDecoderMpeg4);
1139     object_class->finalize      = (GDestroyNotify)gst_vaapi_decoder_finalize;
1140
1141     decoder_class->create       = gst_vaapi_decoder_mpeg4_create;
1142     decoder_class->destroy      = gst_vaapi_decoder_mpeg4_destroy;
1143     decoder_class->parse        = gst_vaapi_decoder_mpeg4_parse;
1144     decoder_class->decode       = gst_vaapi_decoder_mpeg4_decode;
1145
1146     decoder_class->decode_codec_data =
1147         gst_vaapi_decoder_mpeg4_decode_codec_data;
1148 }
1149
1150 static inline const GstVaapiDecoderClass *
1151 gst_vaapi_decoder_mpeg4_class(void)
1152 {
1153     static GstVaapiDecoderMpeg4Class g_class;
1154     static gsize g_class_init = FALSE;
1155
1156     if (g_once_init_enter(&g_class_init)) {
1157         gst_vaapi_decoder_mpeg4_class_init(&g_class);
1158         g_once_init_leave(&g_class_init, TRUE);
1159     }
1160     return GST_VAAPI_DECODER_CLASS(&g_class);
1161 }
1162
1163 /**
1164  * gst_vaapi_decoder_mpeg4_new:
1165  * @display: a #GstVaapiDisplay
1166  * @caps: a #GstCaps holding codec information
1167  *
1168  * Creates a new #GstVaapiDecoder for MPEG-2 decoding.  The @caps can
1169  * hold extra information like codec-data and pictured coded size.
1170  *
1171  * Return value: the newly allocated #GstVaapiDecoder object
1172  */
1173 GstVaapiDecoder *
1174 gst_vaapi_decoder_mpeg4_new(GstVaapiDisplay *display, GstCaps *caps)
1175 {
1176     return gst_vaapi_decoder_new(gst_vaapi_decoder_mpeg4_class(),
1177         display, caps);
1178 }