h265parse: Detect height change on field-based interlaced files
[platform/upstream/gstreamer.git] / gst / videoparsers / gstmpegvideoparse.c
1 /* GStreamer
2  * Copyright (C) <2007> Jan Schmidt <thaytan@mad.scientist.com>
3  * Copyright (C) <2011> Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
4  * Copyright (C) <2011> Thibault Saunier <thibault.saunier@collabora.com>
5  * Copyright (C) <2011> Collabora ltd
6  * Copyright (C) <2011> Nokia Corporation
7  * Copyright (C) <2011> Intel Corporation
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <string.h>
30 #include <gst/base/base.h>
31 #include <gst/pbutils/pbutils.h>
32 #include <gst/codecparsers/gstmpegvideometa.h>
33
34 #include "gstmpegvideoparse.h"
35
36 GST_DEBUG_CATEGORY (mpegv_parse_debug);
37 #define GST_CAT_DEFAULT mpegv_parse_debug
38
39 static GstStaticPadTemplate src_template =
40 GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC,
41     GST_PAD_ALWAYS,
42     GST_STATIC_CAPS ("video/mpeg, "
43         "mpegversion = (int) [1, 2], "
44         "parsed = (boolean) true, " "systemstream = (boolean) false")
45     );
46
47 static GstStaticPadTemplate sink_template =
48 GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK,
49     GST_PAD_ALWAYS,
50     GST_STATIC_CAPS ("video/mpeg, "
51         "mpegversion = (int) [1, 2], " "systemstream = (boolean) false")
52     );
53
54 /* Properties */
55 #define DEFAULT_PROP_DROP       TRUE
56 #define DEFAULT_PROP_GOP_SPLIT  FALSE
57
58 enum
59 {
60   PROP_0,
61   PROP_DROP,
62   PROP_GOP_SPLIT
63 };
64
65 #define parent_class gst_mpegv_parse_parent_class
66 G_DEFINE_TYPE (GstMpegvParse, gst_mpegv_parse, GST_TYPE_BASE_PARSE);
67
68 static gboolean gst_mpegv_parse_start (GstBaseParse * parse);
69 static gboolean gst_mpegv_parse_stop (GstBaseParse * parse);
70 static GstFlowReturn gst_mpegv_parse_handle_frame (GstBaseParse * parse,
71     GstBaseParseFrame * frame, gint * skipsize);
72 static GstFlowReturn gst_mpegv_parse_parse_frame (GstBaseParse * parse,
73     GstBaseParseFrame * frame);
74 static gboolean gst_mpegv_parse_set_caps (GstBaseParse * parse, GstCaps * caps);
75 static GstCaps *gst_mpegv_parse_get_caps (GstBaseParse * parse,
76     GstCaps * filter);
77 static GstFlowReturn gst_mpegv_parse_pre_push_frame (GstBaseParse * parse,
78     GstBaseParseFrame * frame);
79 static gboolean gst_mpegv_parse_sink_query (GstBaseParse * parse,
80     GstQuery * query);
81
82 static void gst_mpegv_parse_set_property (GObject * object, guint prop_id,
83     const GValue * value, GParamSpec * pspec);
84 static void gst_mpegv_parse_get_property (GObject * object, guint prop_id,
85     GValue * value, GParamSpec * pspec);
86
87 static void
88 gst_mpegv_parse_set_property (GObject * object, guint property_id,
89     const GValue * value, GParamSpec * pspec)
90 {
91   GstMpegvParse *parse = GST_MPEGVIDEO_PARSE (object);
92
93   switch (property_id) {
94     case PROP_DROP:
95       parse->drop = g_value_get_boolean (value);
96       break;
97     case PROP_GOP_SPLIT:
98       parse->gop_split = g_value_get_boolean (value);
99       break;
100     default:
101       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
102   }
103 }
104
105 static void
106 gst_mpegv_parse_get_property (GObject * object, guint property_id,
107     GValue * value, GParamSpec * pspec)
108 {
109   GstMpegvParse *parse = GST_MPEGVIDEO_PARSE (object);
110
111   switch (property_id) {
112     case PROP_DROP:
113       g_value_set_boolean (value, parse->drop);
114       break;
115     case PROP_GOP_SPLIT:
116       g_value_set_boolean (value, parse->gop_split);
117       break;
118     default:
119       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
120   }
121 }
122
123 static void
124 gst_mpegv_parse_class_init (GstMpegvParseClass * klass)
125 {
126   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
127   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
128   GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
129
130   GST_DEBUG_CATEGORY_INIT (mpegv_parse_debug, "mpegvideoparse", 0,
131       "MPEG-1/2 video parser");
132
133   parent_class = g_type_class_peek_parent (klass);
134
135   gobject_class->set_property = gst_mpegv_parse_set_property;
136   gobject_class->get_property = gst_mpegv_parse_get_property;
137
138   g_object_class_install_property (gobject_class, PROP_DROP,
139       g_param_spec_boolean ("drop", "drop",
140           "Drop data until valid configuration data is received either "
141           "in the stream or through caps", DEFAULT_PROP_DROP,
142           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
143
144   g_object_class_install_property (gobject_class, PROP_GOP_SPLIT,
145       g_param_spec_boolean ("gop-split", "gop-split",
146           "Split frame when encountering GOP", DEFAULT_PROP_GOP_SPLIT,
147           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
148
149   gst_element_class_add_static_pad_template (element_class, &src_template);
150   gst_element_class_add_static_pad_template (element_class, &sink_template);
151
152   gst_element_class_set_static_metadata (element_class,
153       "MPEG video elementary stream parser",
154       "Codec/Parser/Video",
155       "Parses and frames MPEG-1 and MPEG-2 elementary video streams",
156       "Wim Taymans <wim.taymans@ccollabora.co.uk>, "
157       "Jan Schmidt <thaytan@mad.scientist.com>, "
158       "Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>");
159
160   /* Override BaseParse vfuncs */
161   parse_class->start = GST_DEBUG_FUNCPTR (gst_mpegv_parse_start);
162   parse_class->stop = GST_DEBUG_FUNCPTR (gst_mpegv_parse_stop);
163   parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_mpegv_parse_handle_frame);
164   parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_mpegv_parse_set_caps);
165   parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_mpegv_parse_get_caps);
166   parse_class->pre_push_frame =
167       GST_DEBUG_FUNCPTR (gst_mpegv_parse_pre_push_frame);
168   parse_class->sink_query = GST_DEBUG_FUNCPTR (gst_mpegv_parse_sink_query);
169 }
170
171 static void
172 gst_mpegv_parse_init (GstMpegvParse * parse)
173 {
174   parse->config_flags = FLAG_NONE;
175
176   gst_base_parse_set_pts_interpolation (GST_BASE_PARSE (parse), FALSE);
177   gst_base_parse_set_infer_ts (GST_BASE_PARSE (parse), FALSE);
178   GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (parse));
179   GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (parse));
180 }
181
182 static void
183 gst_mpegv_parse_reset_frame (GstMpegvParse * mpvparse)
184 {
185   /* done parsing; reset state */
186   mpvparse->last_sc = -1;
187   mpvparse->seq_size = 0;
188   mpvparse->seq_offset = -1;
189   mpvparse->pic_offset = -1;
190   mpvparse->frame_repeat_count = 0;
191   memset (mpvparse->ext_offsets, 0, sizeof (mpvparse->ext_offsets));
192   mpvparse->ext_count = 0;
193   mpvparse->slice_count = 0;
194   mpvparse->slice_offset = 0;
195 }
196
197 static void
198 gst_mpegv_parse_reset (GstMpegvParse * mpvparse)
199 {
200   gst_mpegv_parse_reset_frame (mpvparse);
201   mpvparse->profile = 0;
202   mpvparse->update_caps = TRUE;
203   mpvparse->send_codec_tag = TRUE;
204   mpvparse->send_mpeg_meta = TRUE;
205
206   gst_buffer_replace (&mpvparse->config, NULL);
207   memset (&mpvparse->sequencehdr, 0, sizeof (mpvparse->sequencehdr));
208   memset (&mpvparse->sequenceext, 0, sizeof (mpvparse->sequenceext));
209   memset (&mpvparse->sequencedispext, 0, sizeof (mpvparse->sequencedispext));
210   memset (&mpvparse->pichdr, 0, sizeof (mpvparse->pichdr));
211   memset (&mpvparse->picext, 0, sizeof (mpvparse->picext));
212
213   mpvparse->seqhdr_updated = FALSE;
214   mpvparse->seqext_updated = FALSE;
215   mpvparse->seqdispext_updated = FALSE;
216   mpvparse->picext_updated = FALSE;
217   mpvparse->quantmatrext_updated = FALSE;
218 }
219
220 static gboolean
221 gst_mpegv_parse_sink_query (GstBaseParse * parse, GstQuery * query)
222 {
223   gboolean res;
224   GstMpegvParse *mpvparse = GST_MPEGVIDEO_PARSE (parse);
225
226   res = GST_BASE_PARSE_CLASS (parent_class)->sink_query (parse, query);
227
228   if (res && GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION) {
229     mpvparse->send_mpeg_meta =
230         gst_query_find_allocation_meta (query, GST_MPEG_VIDEO_META_API_TYPE,
231         NULL);
232
233     GST_DEBUG_OBJECT (parse, "Downstream can handle GstMpegVideo GstMeta : %d",
234         mpvparse->send_mpeg_meta);
235   }
236
237   return res;
238 }
239
240 static gboolean
241 gst_mpegv_parse_start (GstBaseParse * parse)
242 {
243   GstMpegvParse *mpvparse = GST_MPEGVIDEO_PARSE (parse);
244
245   GST_DEBUG_OBJECT (parse, "start");
246
247   gst_mpegv_parse_reset (mpvparse);
248   /* at least this much for a valid frame */
249   gst_base_parse_set_min_frame_size (parse, 6);
250
251   return TRUE;
252 }
253
254 static gboolean
255 gst_mpegv_parse_stop (GstBaseParse * parse)
256 {
257   GstMpegvParse *mpvparse = GST_MPEGVIDEO_PARSE (parse);
258
259   GST_DEBUG_OBJECT (parse, "stop");
260
261   gst_mpegv_parse_reset (mpvparse);
262
263   return TRUE;
264 }
265
266 static gboolean
267 gst_mpegv_parse_process_config (GstMpegvParse * mpvparse, GstMapInfo * info,
268     guint size)
269 {
270   GstMpegVideoPacket packet;
271   guint8 *data_with_prefix;
272   gint i;
273
274   if (mpvparse->seq_offset < 4) {
275     /* This shouldn't happen, but just in case... */
276     GST_WARNING_OBJECT (mpvparse, "Sequence header start code missing.");
277     return FALSE;
278   }
279
280   packet.data = info->data;
281   packet.type = GST_MPEG_VIDEO_PACKET_SEQUENCE;
282   packet.offset = mpvparse->seq_offset;
283   packet.size = size - mpvparse->seq_offset;
284   /* pointer to sequence header data including the start code prefix -
285      used for codec private data */
286   data_with_prefix = (guint8 *) packet.data + packet.offset - 4;
287
288   /* only do stuff if something new; only compare first 8 bytes, changes in
289      quantiser matrix or bitrate don't matter here. Also changing the
290      matrices in codec_data seems to cause problem with decoders */
291   if (mpvparse->config &&
292       gst_buffer_memcmp (mpvparse->config, 0, data_with_prefix, MIN (size,
293               8)) == 0) {
294     return TRUE;
295   }
296
297   if (!gst_mpeg_video_packet_parse_sequence_header (&packet,
298           &mpvparse->sequencehdr)) {
299     GST_DEBUG_OBJECT (mpvparse,
300         "failed to parse config data (size %d) at offset %d",
301         size, mpvparse->seq_offset);
302     return FALSE;
303   }
304
305   mpvparse->seqhdr_updated = TRUE;
306
307   GST_LOG_OBJECT (mpvparse, "accepting parsed config size %d", size);
308
309   /* Set mpeg version, and parse sequence extension */
310   mpvparse->config_flags = FLAG_NONE;
311   for (i = 0; i < mpvparse->ext_count; ++i) {
312     packet.type = GST_MPEG_VIDEO_PACKET_EXTENSION;
313     packet.offset = mpvparse->ext_offsets[i];
314     packet.size = (gint) size - mpvparse->ext_offsets[i];
315     mpvparse->config_flags |= FLAG_MPEG2;
316     if (packet.size > 1) {
317       switch (packet.data[packet.offset] >> 4) {
318         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
319           if (gst_mpeg_video_packet_parse_sequence_extension (&packet,
320                   &mpvparse->sequenceext)) {
321             GST_LOG_OBJECT (mpvparse, "Read Sequence Extension");
322             mpvparse->config_flags |= FLAG_SEQUENCE_EXT;
323             mpvparse->seqext_updated = TRUE;
324           }
325           break;
326         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
327           if (gst_mpeg_video_packet_parse_sequence_display_extension (&packet,
328                   &mpvparse->sequencedispext)) {
329             GST_LOG_OBJECT (mpvparse, "Read Sequence Display Extension");
330             mpvparse->config_flags |= FLAG_SEQUENCE_DISPLAY_EXT;
331             mpvparse->seqdispext_updated = TRUE;
332           }
333           break;
334         case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
335           if (gst_mpeg_video_packet_parse_quant_matrix_extension (&packet,
336                   &mpvparse->quantmatrext)) {
337             GST_LOG_OBJECT (mpvparse, "Read Quantization Matrix Extension");
338             mpvparse->quantmatrext_updated = TRUE;
339           }
340           break;
341       }
342     }
343   }
344   if (mpvparse->config_flags & FLAG_MPEG2) {
345     /* Update the sequence header based on extensions */
346     GstMpegVideoSequenceExt *seqext = NULL;
347     GstMpegVideoSequenceDisplayExt *seqdispext = NULL;
348
349     if (mpvparse->config_flags & FLAG_SEQUENCE_EXT)
350       seqext = &mpvparse->sequenceext;
351     if (mpvparse->config_flags & FLAG_SEQUENCE_DISPLAY_EXT)
352       seqdispext = &mpvparse->sequencedispext;
353
354     gst_mpeg_video_finalise_mpeg2_sequence_header (&mpvparse->sequencehdr,
355         seqext, seqdispext);
356   }
357
358   if (mpvparse->fps_num == 0 || mpvparse->fps_den == 0) {
359     mpvparse->fps_num = mpvparse->sequencehdr.fps_n;
360     mpvparse->fps_den = mpvparse->sequencehdr.fps_d;
361   }
362
363   /* parsing ok, so accept it as new config */
364   if (mpvparse->config != NULL)
365     gst_buffer_unref (mpvparse->config);
366
367   mpvparse->config = gst_buffer_new_and_alloc (size);
368   gst_buffer_fill (mpvparse->config, 0, data_with_prefix, size);
369
370   /* trigger src caps update */
371   mpvparse->update_caps = TRUE;
372
373   return TRUE;
374 }
375
376 /* FIXME : Move these functions to libgstcodecparser for usage by
377  * more elements/code */
378 #ifndef GST_DISABLE_GST_DEBUG
379 static const gchar *
380 picture_start_code_name (guint8 psc)
381 {
382   guint i;
383   const struct
384   {
385     guint8 psc;
386     const gchar *name;
387   } psc_names[] = {
388     {
389     0x00, "Picture Start"}, {
390     0xb0, "Reserved"}, {
391     0xb1, "Reserved"}, {
392     0xb2, "User Data Start"}, {
393     0xb3, "Sequence Header Start"}, {
394     0xb4, "Sequence Error"}, {
395     0xb5, "Extension Start"}, {
396     0xb6, "Reserved"}, {
397     0xb7, "Sequence End"}, {
398     0xb8, "Group Start"}, {
399     0xb9, "Program End"}
400   };
401   if (psc < 0xB0 && psc > 0)
402     return "Slice Start";
403
404   for (i = 0; i < G_N_ELEMENTS (psc_names); i++)
405     if (psc_names[i].psc == psc)
406       return psc_names[i].name;
407
408   return "UNKNOWN";
409 };
410
411 static const gchar *
412 picture_type_name (guint8 pct)
413 {
414   guint i;
415   const struct
416   {
417     guint8 pct;
418     const gchar *name;
419   } pct_names[] = {
420     {
421     0, "Forbidden"}, {
422     1, "I Frame"}, {
423     2, "P Frame"}, {
424     3, "B Frame"}, {
425     4, "DC Intra Coded (Shall Not Be Used!)"}
426   };
427
428   for (i = 0; i < G_N_ELEMENTS (pct_names); i++)
429     if (pct_names[i].pct == pct)
430       return pct_names[i].name;
431
432   return "Reserved/Unknown";
433 }
434 #endif /* GST_DISABLE_GST_DEBUG */
435
436 static void
437 parse_packet_extension (GstMpegvParse * mpvparse, GstMapInfo * info, guint off)
438 {
439   GstMpegVideoPacket packet;
440
441   packet.data = info->data;
442   packet.type = GST_MPEG_VIDEO_PACKET_EXTENSION;
443   packet.offset = off;
444   packet.size = info->size - off;
445
446   /* FIXME : WE ARE ASSUMING IT IS A *PICTURE* EXTENSION */
447   if (gst_mpeg_video_packet_parse_picture_extension (&packet,
448           &mpvparse->picext)) {
449     mpvparse->frame_repeat_count = 1;
450
451     if (mpvparse->picext.repeat_first_field) {
452       if (mpvparse->sequenceext.progressive) {
453         if (mpvparse->picext.top_field_first)
454           mpvparse->frame_repeat_count = 5;
455         else
456           mpvparse->frame_repeat_count = 3;
457       } else if (mpvparse->picext.progressive_frame) {
458         mpvparse->frame_repeat_count = 2;
459       }
460     }
461     mpvparse->picext_updated = TRUE;
462   }
463 }
464
465 static void
466 parse_user_data_packet (GstMpegvParse * mpvparse, const guint8 * data,
467     guint size)
468 {
469   GstByteReader br;
470   GstVideoParseUtilsField field = GST_VIDEO_PARSE_UTILS_FIELD_1;
471   gst_byte_reader_init (&br, data, size);
472
473   if (mpvparse->picext.picture_structure ==
474       (guint8) GST_MPEG_VIDEO_PICTURE_STRUCTURE_BOTTOM_FIELD)
475     field = GST_VIDEO_PARSE_UTILS_FIELD_2;
476   gst_video_parse_user_data ((GstElement *) mpvparse, &mpvparse->user_data, &br,
477       field, ITU_T_T35_MANUFACTURER_US_ATSC);
478
479 }
480
481 /* caller guarantees at least start code in @buf at @off ( - 4)*/
482 /* for off == 4 initial code; returns TRUE if code starts a frame
483  * otherwise returns TRUE if code terminates preceding frame */
484 static gboolean
485 gst_mpegv_parse_process_sc (GstMpegvParse * mpvparse,
486     GstMapInfo * info, gint off, GstMpegVideoPacket * packet,
487     gboolean * need_more)
488 {
489   gboolean ret = FALSE, checkconfig = TRUE;
490
491   GST_LOG_OBJECT (mpvparse, "process startcode %x (%s) offset:%d", packet->type,
492       picture_start_code_name (packet->type), off);
493
494   *need_more = FALSE;
495
496   switch (packet->type) {
497     case GST_MPEG_VIDEO_PACKET_PICTURE:
498       GST_LOG_OBJECT (mpvparse, "startcode is PICTURE");
499       /* picture is aggregated with preceding sequence/gop, if any.
500        * so, picture start code only ends if already a previous one */
501       if (mpvparse->pic_offset < 0)
502         mpvparse->pic_offset = off;
503       else
504         ret = (off != mpvparse->pic_offset);
505       /* but it's a valid starting one */
506       if (off == 4)
507         ret = TRUE;
508       break;
509     case GST_MPEG_VIDEO_PACKET_SEQUENCE:
510       GST_LOG_OBJECT (mpvparse, "startcode is SEQUENCE");
511       if (mpvparse->seq_offset < 0)
512         mpvparse->seq_offset = off;
513       ret = TRUE;
514       break;
515     case GST_MPEG_VIDEO_PACKET_GOP:
516       GST_LOG_OBJECT (mpvparse, "startcode is GOP");
517       if (mpvparse->seq_offset >= 0)
518         ret = mpvparse->gop_split;
519       else
520         ret = TRUE;
521       break;
522     case GST_MPEG_VIDEO_PACKET_EXTENSION:
523       mpvparse->config_flags |= FLAG_MPEG2;
524       GST_LOG_OBJECT (mpvparse, "startcode is VIDEO PACKET EXTENSION");
525       if (mpvparse->pic_offset >= 0) {
526         GST_LOG_OBJECT (mpvparse, "... considered PICTURE EXTENSION");
527         parse_packet_extension (mpvparse, info, off);
528       } else {
529         GST_LOG_OBJECT (mpvparse, "... considered SEQUENCE EXTENSION");
530         if (mpvparse->ext_count < G_N_ELEMENTS (mpvparse->ext_offsets))
531           mpvparse->ext_offsets[mpvparse->ext_count++] = off;
532       }
533       checkconfig = FALSE;
534       break;
535     case GST_MPEG_VIDEO_PACKET_USER_DATA:
536       GST_LOG_OBJECT (mpvparse, "USER_DATA packet of %d bytes", packet->size);
537
538       if (packet->size < 0) {
539         GST_LOG_OBJECT (mpvparse, "no size yet, need more data");
540         *need_more = TRUE;
541         return FALSE;
542       }
543
544       parse_user_data_packet (mpvparse, info->data + off, packet->size);
545       checkconfig = FALSE;
546       break;
547     default:
548       if (GST_MPEG_VIDEO_PACKET_IS_SLICE (packet->type)) {
549         mpvparse->slice_count++;
550         if (mpvparse->slice_offset == 0)
551           mpvparse->slice_offset = off - 4;
552       }
553       checkconfig = FALSE;
554       break;
555   }
556
557   /* set size to avoid processing config again */
558   if (checkconfig && mpvparse->seq_offset >= 0 && off != mpvparse->seq_offset &&
559       !mpvparse->seq_size) {
560     /* should always be at start */
561     g_assert (mpvparse->seq_offset <= 4);
562     gst_mpegv_parse_process_config (mpvparse, info, off - mpvparse->seq_offset);
563     mpvparse->seq_size = off - mpvparse->seq_offset;
564   }
565
566   /* extract some picture info if there is any in the frame being terminated */
567   if (ret && mpvparse->pic_offset >= 0 && mpvparse->pic_offset < off) {
568     GstMpegVideoPacket header;
569
570     header.data = info->data;
571     header.type = GST_MPEG_VIDEO_PACKET_PICTURE;
572     header.offset = mpvparse->pic_offset;
573     header.size = info->size - mpvparse->pic_offset;
574     if (gst_mpeg_video_packet_parse_picture_header (&header, &mpvparse->pichdr))
575       GST_LOG_OBJECT (mpvparse, "picture_coding_type %d (%s), ending"
576           "frame of size %d", mpvparse->pichdr.pic_type,
577           picture_type_name (mpvparse->pichdr.pic_type), off - 4);
578     else
579       GST_LOG_OBJECT (mpvparse, "Couldn't parse picture at offset %d",
580           mpvparse->pic_offset);
581
582     /* if terminating packet is a picture, we need to check if it has same TSN as the picture that is being
583        terminated. If it does, we need to keep those together, as these packets are two fields of the same
584        frame */
585     if (packet->type == GST_MPEG_VIDEO_PACKET_PICTURE
586         && (mpvparse->config_flags & FLAG_SEQUENCE_EXT)
587         && !mpvparse->sequenceext.progressive) {
588       if (info->size - off < 2) {       /* we need at least two bytes to read the TSN */
589         *need_more = TRUE;
590         ret = FALSE;
591       } else {
592         /* TSN is stored in first 10 bits */
593         int tsn = info->data[off] << 2 | (info->data[off + 1] & 0xC0) >> 6;
594
595         if (tsn == mpvparse->pichdr.tsn)        /* prevent termination if TSN is same */
596           ret = FALSE;
597       }
598     }
599   }
600
601   return ret;
602 }
603
604 /* FIXME move into baseparse, or anything equivalent;
605  * see https://bugzilla.gnome.org/show_bug.cgi?id=650093
606  * #define GST_BASE_PARSE_FRAME_FLAG_PARSING   0x100000 */
607
608 static inline void
609 update_frame_parsing_status (GstMpegvParse * mpvparse,
610     GstBaseParseFrame * frame)
611 {
612   /* avoid stale cached parsing state */
613   if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME) {
614     GST_LOG_OBJECT (mpvparse, "parsing new frame");
615     gst_mpegv_parse_reset_frame (mpvparse);
616   } else {
617     GST_LOG_OBJECT (mpvparse, "resuming frame parsing");
618   }
619 }
620
621 static GstFlowReturn
622 gst_mpegv_parse_handle_frame (GstBaseParse * parse,
623     GstBaseParseFrame * frame, gint * skipsize)
624 {
625   GstFlowReturn flowret = GST_FLOW_OK;
626   GstMpegvParse *mpvparse = GST_MPEGVIDEO_PARSE (parse);
627   GstBuffer *buf = frame->buffer;
628   gboolean ret = FALSE;
629   gint off = 0;
630   GstMpegVideoPacket packet;
631   guint8 *data;
632   gint size;
633   gboolean need_more = FALSE;
634   GstMapInfo map;
635
636   update_frame_parsing_status (mpvparse, frame);
637
638   gst_buffer_map (buf, &map, GST_MAP_READ);
639   data = map.data;
640   size = map.size;
641
642 retry:
643   /* at least start code and subsequent byte */
644   if (G_UNLIKELY (size < 5 + off))
645     goto exit;
646
647   /* if already found a previous start code, e.g. start of frame, go for next */
648   if (mpvparse->last_sc >= 0) {
649     packet.offset = mpvparse->last_sc;
650     packet.size = 0;
651     goto next;
652   }
653
654   if (!gst_mpeg_video_parse (&packet, data, size, off)) {
655     /* didn't find anything that looks like a sync word, skip */
656     GST_LOG_OBJECT (mpvparse, "no start code found");
657     *skipsize = size - 3;
658     goto exit;
659   }
660
661   off = packet.offset - 4;
662   GST_LOG_OBJECT (mpvparse, "possible sync at buffer offset %d", off);
663
664   /* possible frame header, but not at offset 0? skip bytes before sync */
665   if (G_UNLIKELY (off > 0)) {
666     *skipsize = off;
667     goto exit;
668   }
669
670   /* note: initial start code is assumed at offset 0 by subsequent code */
671
672   /* examine start code, see if it looks like an initial start code */
673   if (gst_mpegv_parse_process_sc (mpvparse, &map, 4, &packet, &need_more)) {
674     /* found sc */
675     GST_LOG_OBJECT (mpvparse, "valid start code found");
676     mpvparse->last_sc = 0;
677   } else {
678     off++;
679     gst_mpegv_parse_reset_frame (mpvparse);
680     GST_LOG_OBJECT (mpvparse, "invalid start code");
681     goto retry;
682   }
683
684 next:
685   /* start is fine as of now */
686   *skipsize = 0;
687   /* terminating start code may have been found in prev scan already */
688   if (((gint) packet.size) >= 0) {
689     off = packet.offset + packet.size;
690     /* so now we have start code at start of data; locate next start code */
691     if (!gst_mpeg_video_parse (&packet, data, size, off)) {
692       off = -1;
693     } else {
694       g_assert (packet.offset >= 4);
695       off = packet.offset - 4;
696     }
697   } else {
698     off = -1;
699   }
700
701   GST_LOG_OBJECT (mpvparse, "next start code at %d", off);
702   if (off < 0) {
703     off = size - 3;
704     goto need_more;
705   } else {
706     /* decide whether this startcode ends a frame */
707     ret = gst_mpegv_parse_process_sc (mpvparse, &map, off + 4, &packet,
708         &need_more);
709     /* in rare cases, might need to peek past start code */
710     if (need_more) {
711       GST_LOG_OBJECT (mpvparse, "need more data (past start code");
712       ret = FALSE;
713       goto need_more;
714     }
715   }
716
717   if (!ret)
718     goto next;
719
720 exit:
721   gst_buffer_unmap (buf, &map);
722
723   if (ret) {
724     GstFlowReturn res;
725
726     *skipsize = 0;
727     g_assert (off <= map.size);
728     res = gst_mpegv_parse_parse_frame (parse, frame);
729     if (res == GST_BASE_PARSE_FLOW_DROPPED)
730       frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
731     flowret = gst_base_parse_finish_frame (parse, frame, off);
732     /* Reset local information */
733     mpvparse->seqhdr_updated = FALSE;
734     mpvparse->seqext_updated = FALSE;
735     mpvparse->seqdispext_updated = FALSE;
736     mpvparse->picext_updated = FALSE;
737     mpvparse->quantmatrext_updated = FALSE;
738   }
739
740   return flowret;
741
742 need_more:
743   /* if draining, take all */
744   if (GST_BASE_PARSE_DRAINING (parse)) {
745     GST_LOG_OBJECT (mpvparse, "draining, accepting all data");
746     off = size;
747     ret = TRUE;
748   } else {
749     GST_LOG_OBJECT (mpvparse, "need more data");
750     /* resume scan where we left it */
751     mpvparse->last_sc = off;
752     /* request best next available */
753     off = G_MAXUINT;
754   }
755   goto exit;
756 }
757
758 static void
759 gst_mpegv_parse_update_src_caps (GstMpegvParse * mpvparse)
760 {
761   GstCaps *caps = NULL;
762   GstStructure *s = NULL;
763
764   /* only update if no src caps yet or explicitly triggered */
765   if (G_LIKELY (gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (mpvparse)) &&
766           !mpvparse->update_caps))
767     return;
768
769   /* carry over input caps as much as possible; override with our own stuff */
770   caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (mpvparse));
771   if (caps) {
772     caps = gst_caps_make_writable (caps);
773     s = gst_caps_get_structure (caps, 0);
774   } else {
775     caps = gst_caps_new_empty_simple ("video/mpeg");
776   }
777
778   /* typically we don't output buffers until we have properly parsed some
779    * config data, so we should at least know about version.
780    * If not, it means it has been requested not to drop data, and
781    * upstream and/or app must know what they are doing ... */
782   gst_caps_set_simple (caps,
783       "mpegversion", G_TYPE_INT, (mpvparse->config_flags & FLAG_MPEG2) ? 2 : 1,
784       NULL);
785
786   gst_caps_set_simple (caps, "systemstream", G_TYPE_BOOLEAN, FALSE,
787       "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
788
789   if (mpvparse->sequencehdr.width > 0 && mpvparse->sequencehdr.height > 0) {
790     GstMpegVideoSequenceDisplayExt *seqdispext;
791     gint width, height;
792
793     width = mpvparse->sequencehdr.width;
794     height = mpvparse->sequencehdr.height;
795
796     if (mpvparse->config_flags & FLAG_SEQUENCE_DISPLAY_EXT) {
797       seqdispext = &mpvparse->sequencedispext;
798
799       if (seqdispext->display_horizontal_size <= width
800           && seqdispext->display_vertical_size <= height) {
801         width = seqdispext->display_horizontal_size;
802         height = seqdispext->display_vertical_size;
803         GST_INFO_OBJECT (mpvparse,
804             "stream has display extension: display_width=%d display_height=%d",
805             width, height);
806       }
807     }
808     gst_caps_set_simple (caps, "width", G_TYPE_INT, width,
809         "height", G_TYPE_INT, height, NULL);
810   }
811
812   /* perhaps we have a framerate */
813   {
814     gint fps_num = mpvparse->fps_num;
815     gint fps_den = mpvparse->fps_den;
816     GstClockTime latency;
817
818     /* upstream overrides */
819     if (s && gst_structure_has_field (s, "framerate"))
820       gst_structure_get_fraction (s, "framerate", &fps_num, &fps_den);
821
822     if (fps_den > 0 && fps_num > 0) {
823       gst_caps_set_simple (caps, "framerate",
824           GST_TYPE_FRACTION, fps_num, fps_den, NULL);
825       gst_base_parse_set_frame_rate (GST_BASE_PARSE (mpvparse),
826           fps_num, fps_den, 0, 0);
827       latency = gst_util_uint64_scale (GST_SECOND, fps_den, fps_num);
828       gst_base_parse_set_latency (GST_BASE_PARSE (mpvparse), latency, latency);
829     }
830   }
831
832   /* or pixel-aspect-ratio */
833   if (mpvparse->sequencehdr.par_w && mpvparse->sequencehdr.par_h > 0 &&
834       (!s || !gst_structure_has_field (s, "pixel-aspect-ratio"))) {
835     gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
836         mpvparse->sequencehdr.par_w, mpvparse->sequencehdr.par_h, NULL);
837   }
838
839   if (mpvparse->config != NULL) {
840     gst_caps_set_simple (caps, "codec_data",
841         GST_TYPE_BUFFER, mpvparse->config, NULL);
842   }
843
844   if (mpvparse->config_flags & FLAG_SEQUENCE_EXT) {
845     guint8 escape = mpvparse->sequenceext.profile_level_escape_bit;
846     const guint profile_c = mpvparse->sequenceext.profile;
847     const guint level_c = mpvparse->sequenceext.level;
848     const gchar *profile = NULL, *level = NULL;
849     /*
850      * Profile indication - 1 => High, 2 => Spatially Scalable,
851      *                      3 => SNR Scalable, 4 => Main, 5 => Simple
852      * 4:2:2 and Multi-view have profile = 0, with the escape bit set to 1
853      */
854     const gchar *const profiles[] =
855         { "4:2:2", "high", "spatial", "snr", "main", "simple" };
856     /*
857      * Level indication - 4 => High, 6 => High-1440, 8 => Main, 10 => Low,
858      *                    except in the case of profile = 0
859      */
860     const gchar *const levels[] = { "high", "high-1440", "main", "low" };
861
862     if (escape) {
863       /* Non-hierarchical profile */
864       switch (level_c) {
865         case 2:
866           level = levels[0];
867         case 5:
868           if (!level)
869             level = levels[2];
870           profile = "4:2:2";
871           break;
872         case 10:
873           level = levels[0];
874         case 11:
875           if (!level)
876             level = levels[1];
877         case 13:
878           if (!level)
879             level = levels[2];
880         case 14:
881           if (!level)
882             level = levels[3];
883           profile = "multiview";
884           break;
885         default:
886           break;
887       }
888
889     } else {
890       if (profile_c < 6)
891         profile = profiles[profile_c];
892
893       if ((level_c > 3) && (level_c < 11) && (level_c % 2 == 0))
894         level = levels[(level_c >> 1) - 2];
895     }
896
897     GST_DEBUG_OBJECT (mpvparse, "profile:'%s' level:'%s'", profile, level);
898
899     if (profile)
900       gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
901     else
902       GST_DEBUG_OBJECT (mpvparse, "Invalid profile - %u", profile_c);
903
904     if (level)
905       gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
906     else
907       GST_DEBUG_OBJECT (mpvparse, "Invalid level - %u", level_c);
908
909     if (!s || !gst_structure_has_field (s, "interlace-mode"))
910       gst_caps_set_simple (caps, "interlace-mode",
911           G_TYPE_STRING,
912           (mpvparse->sequenceext.progressive ? "progressive" : "mixed"), NULL);
913   }
914
915   gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (mpvparse), caps);
916   gst_caps_unref (caps);
917
918   mpvparse->update_caps = FALSE;
919 }
920
921 static GstFlowReturn
922 gst_mpegv_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
923 {
924   GstMpegvParse *mpvparse = GST_MPEGVIDEO_PARSE (parse);
925   GstBuffer *buffer = frame->buffer;
926
927   if (G_UNLIKELY (mpvparse->pichdr.pic_type == GST_MPEG_VIDEO_PICTURE_TYPE_I))
928     GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
929   else
930     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
931
932   /* maybe only sequence in this buffer, though not recommended,
933    * so mark it as such and force 0 duration */
934   if (G_UNLIKELY (mpvparse->pic_offset < 0)) {
935     GST_DEBUG_OBJECT (mpvparse, "frame holds no picture data");
936     frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NO_FRAME;
937     GST_BUFFER_DURATION (buffer) = 0;
938   }
939
940   if (mpvparse->pic_offset > 4) {
941     gst_base_parse_set_ts_at_offset (parse, mpvparse->pic_offset - 4);
942   }
943
944   if (mpvparse->frame_repeat_count
945       && GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) {
946     GST_BUFFER_DURATION (buffer) =
947         (1 + mpvparse->frame_repeat_count) * GST_BUFFER_DURATION (buffer) / 2;
948   }
949
950   if (G_UNLIKELY (mpvparse->drop && !mpvparse->config)) {
951     GST_DEBUG_OBJECT (mpvparse, "dropping frame as no config yet");
952     return GST_BASE_PARSE_FLOW_DROPPED;
953   }
954
955   gst_mpegv_parse_update_src_caps (mpvparse);
956   return GST_FLOW_OK;
957 }
958
959 static GstFlowReturn
960 gst_mpegv_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
961 {
962   GstMpegvParse *mpvparse = GST_MPEGVIDEO_PARSE (parse);
963   GstTagList *taglist;
964   GstMpegVideoMeta *meta;
965   GstMpegVideoSequenceHdr *seq_hdr = NULL;
966   GstMpegVideoSequenceExt *seq_ext = NULL;
967   GstMpegVideoSequenceDisplayExt *disp_ext = NULL;
968   GstMpegVideoPictureHdr *pic_hdr = NULL;
969   GstMpegVideoPictureExt *pic_ext = NULL;
970   GstMpegVideoQuantMatrixExt *quant_ext = NULL;
971   GstBuffer *parse_buffer = NULL;
972
973   /* tag sending done late enough in hook to ensure pending events
974    * have already been sent */
975
976   if (G_UNLIKELY (mpvparse->send_codec_tag)) {
977     GstCaps *caps;
978
979     /* codec tag */
980     caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
981     if (G_UNLIKELY (caps == NULL)) {
982       if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) {
983         GST_INFO_OBJECT (parse, "Src pad is flushing");
984         return GST_FLOW_FLUSHING;
985       } else {
986         GST_INFO_OBJECT (parse, "Src pad is not negotiated!");
987         return GST_FLOW_NOT_NEGOTIATED;
988       }
989     }
990
991     taglist = gst_tag_list_new_empty ();
992     gst_pb_utils_add_codec_description_to_tag_list (taglist,
993         GST_TAG_VIDEO_CODEC, caps);
994     gst_caps_unref (caps);
995
996     gst_base_parse_merge_tags (parse, taglist, GST_TAG_MERGE_REPLACE);
997     gst_tag_list_unref (taglist);
998
999     mpvparse->send_codec_tag = FALSE;
1000   }
1001
1002   /* usual clipping applies */
1003   frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1004
1005   if (mpvparse->send_mpeg_meta) {
1006     GstBuffer *buf;
1007
1008     if (mpvparse->seqhdr_updated)
1009       seq_hdr = &mpvparse->sequencehdr;
1010     if (mpvparse->seqext_updated)
1011       seq_ext = &mpvparse->sequenceext;
1012     if (mpvparse->seqdispext_updated)
1013       disp_ext = &mpvparse->sequencedispext;
1014     if (mpvparse->picext_updated)
1015       pic_ext = &mpvparse->picext;
1016     if (mpvparse->quantmatrext_updated)
1017       quant_ext = &mpvparse->quantmatrext;
1018     pic_hdr = &mpvparse->pichdr;
1019
1020     GST_DEBUG_OBJECT (mpvparse,
1021         "Adding GstMpegVideoMeta (slice_count:%d, slice_offset:%d)",
1022         mpvparse->slice_count, mpvparse->slice_offset);
1023
1024     if (frame->out_buffer) {
1025       buf = frame->out_buffer = gst_buffer_make_writable (frame->out_buffer);
1026     } else {
1027       buf = frame->buffer = gst_buffer_make_writable (frame->buffer);
1028     }
1029
1030     meta =
1031         gst_buffer_add_mpeg_video_meta (buf, seq_hdr, seq_ext, disp_ext,
1032         pic_hdr, pic_ext, quant_ext);
1033     meta->num_slices = mpvparse->slice_count;
1034     meta->slice_offset = mpvparse->slice_offset;
1035   }
1036
1037   if (frame->out_buffer) {
1038     parse_buffer = frame->out_buffer =
1039         gst_buffer_make_writable (frame->out_buffer);
1040   } else {
1041     parse_buffer = frame->buffer = gst_buffer_make_writable (frame->buffer);
1042   }
1043
1044   if (pic_ext && !pic_ext->progressive_frame) {
1045     GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1046     if (pic_ext->top_field_first)
1047       GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_TFF);
1048   }
1049   gst_video_push_user_data ((GstElement *) mpvparse, &mpvparse->user_data,
1050       parse_buffer);
1051
1052   return GST_FLOW_OK;
1053 }
1054
1055 static gboolean
1056 gst_mpegv_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
1057 {
1058   GstMpegvParse *mpvparse = GST_MPEGVIDEO_PARSE (parse);
1059   GstStructure *s;
1060   const GValue *value;
1061   GstBuffer *buf;
1062
1063   GST_DEBUG_OBJECT (parse, "setcaps called with %" GST_PTR_FORMAT, caps);
1064
1065   s = gst_caps_get_structure (caps, 0);
1066
1067   if ((value = gst_structure_get_value (s, "codec_data")) != NULL
1068       && (buf = gst_value_get_buffer (value))) {
1069     GstMapInfo map;
1070     gst_buffer_map (buf, &map, GST_MAP_READ);
1071     /* best possible parse attempt,
1072      * src caps are based on sink caps so it will end up in there
1073      * whether successful or not */
1074     mpvparse->seq_offset = 4;
1075     gst_mpegv_parse_process_config (mpvparse, &map, gst_buffer_get_size (buf));
1076     gst_buffer_unmap (buf, &map);
1077     gst_mpegv_parse_reset_frame (mpvparse);
1078   }
1079
1080   /* let's not interfere and accept regardless of config parsing success */
1081   return TRUE;
1082 }
1083
1084 static void
1085 remove_fields (GstCaps * caps)
1086 {
1087   guint i, n;
1088
1089   n = gst_caps_get_size (caps);
1090   for (i = 0; i < n; i++) {
1091     GstStructure *s = gst_caps_get_structure (caps, i);
1092
1093     gst_structure_remove_field (s, "parsed");
1094   }
1095 }
1096
1097 static GstCaps *
1098 gst_mpegv_parse_get_caps (GstBaseParse * parse, GstCaps * filter)
1099 {
1100   GstCaps *peercaps, *templ;
1101   GstCaps *res;
1102
1103   templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
1104   if (filter) {
1105     GstCaps *fcopy = gst_caps_copy (filter);
1106     /* Remove the fields we convert */
1107     remove_fields (fcopy);
1108     peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
1109     gst_caps_unref (fcopy);
1110   } else
1111     peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
1112
1113   if (peercaps) {
1114     /* Remove the parsed field */
1115     peercaps = gst_caps_make_writable (peercaps);
1116     remove_fields (peercaps);
1117
1118     res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
1119     gst_caps_unref (peercaps);
1120     gst_caps_unref (templ);
1121   } else {
1122     res = templ;
1123   }
1124
1125   if (filter) {
1126     GstCaps *intersection;
1127
1128     intersection =
1129         gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
1130     gst_caps_unref (res);
1131     res = intersection;
1132   }
1133
1134   return res;
1135 }