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