1 /*
2  * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
3  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation
8  * version 2.1 of the License.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
18  *
19  */
20 
21 /*
22  * Information about the caps fields:
23  *
24  * header-format:
25  *   none: No codec_data and only in-stream headers
26  *
27  *   asf: codec_data as specified in the ASF specification
28  *       Simple/Main profile: 4 byte sequence header without startcode
29  *       Advanced profile: Sequence header and entrypoint with startcodes
30  *
31  *   sequence-layer: codec_data as specified in SMPTE 421M Annex L.2
32  *
33  *
34  * stream-format:
35  *   bdu: BDUs with startcodes
36  *
37  *   bdu-frame: BDUs with startcodes, everything up to and including a frame
38  *       per buffer. This also means everything needed to decode a frame, i.e.
39  *       field and slice BDUs
40  *
41  *   sequence-layer-bdu: Sequence layer in first buffer, then BDUs with startcodes
42  *
43  *   sequence-layer-bdu-frame: Sequence layer in first buffer, then only frame
44  *       BDUs with startcodes, i.e. everything up to and including a frame.
45  *
46  *   sequence-layer-raw-frame: Sequence layer in first buffer, then only frame
47  *       BDUs without startcodes. Only for simple/main profile.
48  *
49  *   sequence-layer-frame-layer: As specified in SMPTE 421M Annex L, sequence-layer
50  *       first, then BDUs inside frame-layer
51  *
52  *   asf: As specified in the ASF specification.
53  *       For simple/main profile a single frame BDU without startcodes per buffer
54  *       For advanced profile one or many BDUs with/without startcodes:
55  *           Startcodes required if non-frame BDU or multiple BDUs per buffer
56  *           unless frame BDU followed by field BDU. In that case only second (field)
57  *           startcode required.
58  *
59  *   frame-layer: As specified in SMPTE 421M Annex L.2
60  *
61  *
62  * If no stream-format is given in the caps we do the following:
63  *
64  *   0) If header-format=asf we assume stream-format=asf
65  *   1) If first buffer starts with sequence header startcode
66  *      we assume stream-format=bdu (or bdu-frame, doesn't matter
67  *      for the input because we're parsing anyway)
68  *   2) If first buffer starts with sequence layer startcode
69  *      1) If followed by sequence header or frame startcode
70  *         we assume stream-format=sequence-layer-bdu (or -bdu-frame,
71  *         doesn't matter for the input because we're parsing anyway)
72  *      2) Otherwise we assume stream-format=sequence-layer-frame-layer
73  *   3) Otherwise
74  *      1) If header-format=sequence-layer we assume stream-format=frame-layer
75  *      2) If header-format=none we error out
76  */
77 
78 #ifdef HAVE_CONFIG_H
79 #include "config.h"
80 #endif
81 
82 #include "gstvc1parse.h"
83 
84 #include <gst/base/base.h>
85 #include <gst/pbutils/pbutils.h>
86 #include <string.h>
87 
88 GST_DEBUG_CATEGORY (vc1_parse_debug);
89 #define GST_CAT_DEFAULT vc1_parse_debug
90 
91 static const struct
92 {
93   gchar str[15];
94   VC1HeaderFormat en;
95 } header_formats[] = {
96   {
97   "none", VC1_HEADER_FORMAT_NONE}, {
98   "asf", VC1_HEADER_FORMAT_ASF}, {
99   "sequence-layer", VC1_HEADER_FORMAT_SEQUENCE_LAYER}
100 };
101 
102 static const struct
103 {
104   gchar str[27];
105   VC1StreamFormat en;
106 } stream_formats[] = {
107   {
108   "bdu", VC1_STREAM_FORMAT_BDU}, {
109   "bdu-frame", VC1_STREAM_FORMAT_BDU_FRAME}, {
110   "sequence-layer-bdu", VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU}, {
111   "sequence-layer-bdu-frame", VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME}, {
112   "sequence-layer-raw-frame", VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME}, {
113   "sequence-layer-frame-layer", VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER}, {
114   "asf", VC1_STREAM_FORMAT_ASF}, {
115   "frame-layer", VC1_STREAM_FORMAT_FRAME_LAYER}
116 };
117 
118 static const struct
119 {
120   gchar str[5];
121   GstVC1ParseFormat en;
122 } parse_formats[] = {
123   {
124   "WMV3", GST_VC1_PARSE_FORMAT_WMV3}, {
125   "WVC1", GST_VC1_PARSE_FORMAT_WVC1}
126 };
127 
128 static const gchar *
stream_format_to_string(VC1StreamFormat stream_format)129 stream_format_to_string (VC1StreamFormat stream_format)
130 {
131   return stream_formats[stream_format].str;
132 }
133 
134 static VC1StreamFormat
stream_format_from_string(const gchar * stream_format)135 stream_format_from_string (const gchar * stream_format)
136 {
137   gint i;
138 
139   for (i = 0; i < G_N_ELEMENTS (stream_formats); i++) {
140     if (strcmp (stream_formats[i].str, stream_format) == 0)
141       return stream_formats[i].en;
142   }
143   return -1;
144 }
145 
146 static const gchar *
header_format_to_string(VC1HeaderFormat header_format)147 header_format_to_string (VC1HeaderFormat header_format)
148 {
149   return header_formats[header_format].str;
150 }
151 
152 static VC1HeaderFormat
header_format_from_string(const gchar * header_format)153 header_format_from_string (const gchar * header_format)
154 {
155   gint i;
156 
157   for (i = 0; i < G_N_ELEMENTS (header_formats); i++) {
158     if (strcmp (header_formats[i].str, header_format) == 0)
159       return header_formats[i].en;
160   }
161   return -1;
162 }
163 
164 static const gchar *
parse_format_to_string(GstVC1ParseFormat format)165 parse_format_to_string (GstVC1ParseFormat format)
166 {
167   return parse_formats[format].str;
168 }
169 
170 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
171     GST_PAD_SINK,
172     GST_PAD_ALWAYS,
173     GST_STATIC_CAPS ("video/x-wmv, wmvversion=(int) 3, "
174         "format=(string) {WVC1, WMV3}"));
175 
176 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
177     GST_PAD_SRC,
178     GST_PAD_ALWAYS,
179     GST_STATIC_CAPS ("video/x-wmv, wmvversion=(int) 3, "
180         "format=(string) {WVC1, WMV3}, "
181         "stream-format=(string) {bdu, bdu-frame, sequence-layer-bdu, "
182         "sequence-layer-bdu-frame, sequence-layer-raw-frame, "
183         "sequence-layer-frame-layer, asf, frame-layer}, "
184         "header-format=(string) {none, asf, sequence-layer}"));
185 
186 
187 #define parent_class gst_vc1_parse_parent_class
188 G_DEFINE_TYPE (GstVC1Parse, gst_vc1_parse, GST_TYPE_BASE_PARSE);
189 
190 static void gst_vc1_parse_finalize (GObject * object);
191 
192 static gboolean gst_vc1_parse_start (GstBaseParse * parse);
193 static gboolean gst_vc1_parse_stop (GstBaseParse * parse);
194 static GstFlowReturn gst_vc1_parse_handle_frame (GstBaseParse * parse,
195     GstBaseParseFrame * frame, gint * skipsize);
196 static GstFlowReturn gst_vc1_parse_pre_push_frame (GstBaseParse * parse,
197     GstBaseParseFrame * frame);
198 static gboolean gst_vc1_parse_set_caps (GstBaseParse * parse, GstCaps * caps);
199 static GstCaps *gst_vc1_parse_get_sink_caps (GstBaseParse * parse,
200     GstCaps * filter);
201 static GstFlowReturn gst_vc1_parse_detect (GstBaseParse * parse,
202     GstBuffer * buffer);
203 
204 static void gst_vc1_parse_reset (GstVC1Parse * vc1parse);
205 static gboolean gst_vc1_parse_handle_seq_layer (GstVC1Parse * vc1parse,
206     GstBuffer * buf, guint offset, guint size);
207 static gboolean gst_vc1_parse_handle_seq_hdr (GstVC1Parse * vc1parse,
208     GstBuffer * buf, guint offset, guint size);
209 static gboolean gst_vc1_parse_handle_entrypoint (GstVC1Parse * vc1parse,
210     GstBuffer * buf, guint offset, guint size);
211 static void gst_vc1_parse_update_stream_format_properties (GstVC1Parse *
212     vc1parse);
213 
214 static void
gst_vc1_parse_class_init(GstVC1ParseClass * klass)215 gst_vc1_parse_class_init (GstVC1ParseClass * klass)
216 {
217   GObjectClass *gobject_class = (GObjectClass *) klass;
218   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
219   GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
220 
221   GST_DEBUG_CATEGORY_INIT (vc1_parse_debug, "vc1parse", 0, "vc1 parser");
222 
223   gobject_class->finalize = gst_vc1_parse_finalize;
224 
225   gst_element_class_add_static_pad_template (element_class, &srctemplate);
226   gst_element_class_add_static_pad_template (element_class, &sinktemplate);
227 
228   gst_element_class_set_static_metadata (element_class, "VC1 parser",
229       "Codec/Parser/Converter/Video",
230       "Parses VC1 streams",
231       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
232 
233   parse_class->start = GST_DEBUG_FUNCPTR (gst_vc1_parse_start);
234   parse_class->stop = GST_DEBUG_FUNCPTR (gst_vc1_parse_stop);
235   parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_vc1_parse_handle_frame);
236   parse_class->pre_push_frame =
237       GST_DEBUG_FUNCPTR (gst_vc1_parse_pre_push_frame);
238   parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_vc1_parse_set_caps);
239   parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_vc1_parse_get_sink_caps);
240   parse_class->detect = GST_DEBUG_FUNCPTR (gst_vc1_parse_detect);
241 }
242 
243 static void
gst_vc1_parse_init(GstVC1Parse * vc1parse)244 gst_vc1_parse_init (GstVC1Parse * vc1parse)
245 {
246   /* Default values for stream-format=raw, i.e.
247    * raw VC1 frames with startcodes */
248   gst_base_parse_set_syncable (GST_BASE_PARSE (vc1parse), TRUE);
249   gst_base_parse_set_has_timing_info (GST_BASE_PARSE (vc1parse), FALSE);
250 
251   gst_vc1_parse_reset (vc1parse);
252   GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (vc1parse));
253   GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (vc1parse));
254 }
255 
256 static void
gst_vc1_parse_finalize(GObject * object)257 gst_vc1_parse_finalize (GObject * object)
258 {
259   /*GstVC1Parse *vc1parse = GST_VC1_PARSE (object); */
260 
261   G_OBJECT_CLASS (parent_class)->finalize (object);
262 }
263 
264 static void
gst_vc1_parse_reset(GstVC1Parse * vc1parse)265 gst_vc1_parse_reset (GstVC1Parse * vc1parse)
266 {
267   vc1parse->profile = -1;
268   vc1parse->level = -1;
269   vc1parse->format = 0;
270   vc1parse->width = 0;
271   vc1parse->height = 0;
272   vc1parse->fps_n = vc1parse->fps_d = 0;
273   vc1parse->frame_duration = GST_CLOCK_TIME_NONE;
274   vc1parse->fps_from_caps = FALSE;
275   vc1parse->par_n = vc1parse->par_d = 0;
276   vc1parse->par_from_caps = FALSE;
277 
278   vc1parse->renegotiate = TRUE;
279   vc1parse->update_caps = TRUE;
280   vc1parse->sent_codec_tag = FALSE;
281 
282   vc1parse->input_header_format = VC1_HEADER_FORMAT_NONE;
283   vc1parse->input_stream_format = VC1_STREAM_FORMAT_BDU;
284   vc1parse->output_header_format = VC1_HEADER_FORMAT_NONE;
285   vc1parse->output_stream_format = VC1_STREAM_FORMAT_BDU;
286   gst_buffer_replace (&vc1parse->seq_layer_buffer, NULL);
287   gst_buffer_replace (&vc1parse->seq_hdr_buffer, NULL);
288   gst_buffer_replace (&vc1parse->entrypoint_buffer, NULL);
289 
290   vc1parse->seq_layer_sent = FALSE;
291   vc1parse->frame_layer_first_frame_sent = FALSE;
292 }
293 
294 static gboolean
gst_vc1_parse_start(GstBaseParse * parse)295 gst_vc1_parse_start (GstBaseParse * parse)
296 {
297   GstVC1Parse *vc1parse = GST_VC1_PARSE (parse);
298 
299   GST_DEBUG_OBJECT (parse, "start");
300   gst_vc1_parse_reset (vc1parse);
301 
302   vc1parse->detecting_stream_format = TRUE;
303 
304   return TRUE;
305 }
306 
307 static gboolean
gst_vc1_parse_stop(GstBaseParse * parse)308 gst_vc1_parse_stop (GstBaseParse * parse)
309 {
310   GstVC1Parse *vc1parse = GST_VC1_PARSE (parse);
311 
312   GST_DEBUG_OBJECT (parse, "stop");
313   gst_vc1_parse_reset (vc1parse);
314 
315   return TRUE;
316 }
317 
318 static gboolean
gst_vc1_parse_is_format_allowed(GstVC1Parse * vc1parse)319 gst_vc1_parse_is_format_allowed (GstVC1Parse * vc1parse)
320 {
321   if (vc1parse->profile == GST_VC1_PROFILE_ADVANCED &&
322       vc1parse->output_stream_format ==
323       VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME) {
324     GST_ERROR_OBJECT (vc1parse,
325         "sequence-layer-raw-frame is not allowed in advanced profile");
326     return FALSE;
327   } else if (vc1parse->profile == GST_VC1_PROFILE_SIMPLE &&
328       (vc1parse->output_stream_format == VC1_STREAM_FORMAT_BDU ||
329           vc1parse->output_stream_format == VC1_STREAM_FORMAT_BDU_FRAME ||
330           vc1parse->output_stream_format ==
331           VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU ||
332           vc1parse->output_stream_format ==
333           VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME)) {
334     GST_ERROR_OBJECT (vc1parse,
335         "output stream-format not allowed in simple profile");
336     return FALSE;
337   }
338 
339   GST_DEBUG_OBJECT (vc1parse, "check output header-format");
340   switch (vc1parse->output_header_format) {
341     case VC1_HEADER_FORMAT_ASF:
342     case VC1_HEADER_FORMAT_SEQUENCE_LAYER:
343       /* Doesn't make sense to have sequence-layer-* stream-format */
344       if (vc1parse->output_stream_format ==
345           VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU ||
346           vc1parse->output_stream_format ==
347           VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME ||
348           vc1parse->output_stream_format ==
349           VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME ||
350           vc1parse->output_stream_format ==
351           VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER)
352         return FALSE;
353       break;
354     case VC1_HEADER_FORMAT_NONE:
355       /* In simple/main profile, there is no sequence header BDU */
356       if (vc1parse->profile != GST_VC1_PROFILE_ADVANCED &&
357           (vc1parse->output_stream_format == VC1_STREAM_FORMAT_BDU ||
358               vc1parse->output_stream_format == VC1_STREAM_FORMAT_BDU_FRAME ||
359               vc1parse->output_stream_format == VC1_STREAM_FORMAT_FRAME_LAYER))
360         return FALSE;
361 
362       /* ASF stream-format doesn't carry sequence header */
363       if (vc1parse->output_stream_format == VC1_STREAM_FORMAT_ASF)
364         return FALSE;
365       break;
366     default:
367       g_assert_not_reached ();
368       break;
369   }
370 
371   if (vc1parse->output_stream_format == vc1parse->input_stream_format)
372     return TRUE;
373 
374   GST_DEBUG_OBJECT (vc1parse, "check stream-format conversion");
375   switch (vc1parse->output_stream_format) {
376     case VC1_STREAM_FORMAT_BDU:
377       if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU_FRAME ||
378           vc1parse->input_stream_format ==
379           VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME ||
380           vc1parse->input_stream_format ==
381           VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME ||
382           vc1parse->input_stream_format ==
383           VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER ||
384           vc1parse->input_stream_format == VC1_STREAM_FORMAT_FRAME_LAYER)
385         goto conversion_not_supported;
386       break;
387 
388     case VC1_STREAM_FORMAT_BDU_FRAME:
389       if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU ||
390           vc1parse->input_stream_format ==
391           VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU ||
392           vc1parse->input_stream_format ==
393           VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER ||
394           vc1parse->input_stream_format == VC1_STREAM_FORMAT_ASF ||
395           vc1parse->input_stream_format == VC1_STREAM_FORMAT_FRAME_LAYER)
396         goto conversion_not_supported;
397 
398       if (vc1parse->input_stream_format ==
399           VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME)
400         return FALSE;
401       break;
402 
403     case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU:
404       if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU_FRAME ||
405           vc1parse->input_stream_format ==
406           VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME ||
407           vc1parse->input_stream_format ==
408           VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME ||
409           vc1parse->input_stream_format ==
410           VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER ||
411           vc1parse->input_stream_format == VC1_STREAM_FORMAT_FRAME_LAYER)
412         goto conversion_not_supported;
413       break;
414 
415     case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME:
416       if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU ||
417           vc1parse->input_stream_format ==
418           VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU ||
419           vc1parse->input_stream_format ==
420           VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER ||
421           vc1parse->input_stream_format == VC1_STREAM_FORMAT_ASF ||
422           vc1parse->input_stream_format == VC1_STREAM_FORMAT_FRAME_LAYER)
423         goto conversion_not_supported;
424 
425       if (vc1parse->input_stream_format ==
426           VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME)
427         return FALSE;
428       break;
429 
430     case VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME:
431       if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU ||
432           vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU_FRAME ||
433           vc1parse->input_stream_format ==
434           VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU ||
435           vc1parse->input_stream_format ==
436           VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME ||
437           vc1parse->input_stream_format ==
438           VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER ||
439           vc1parse->input_stream_format == VC1_STREAM_FORMAT_FRAME_LAYER)
440         goto conversion_not_supported;
441       break;
442 
443     case VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER:
444       if (vc1parse->input_stream_format != VC1_STREAM_FORMAT_FRAME_LAYER &&
445           vc1parse->input_stream_format != VC1_STREAM_FORMAT_ASF)
446         goto conversion_not_supported;
447       break;
448 
449     case VC1_STREAM_FORMAT_ASF:
450       goto conversion_not_supported;
451       break;
452 
453     case VC1_STREAM_FORMAT_FRAME_LAYER:
454       if (vc1parse->input_stream_format !=
455           VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER &&
456           vc1parse->input_stream_format != VC1_STREAM_FORMAT_ASF)
457         goto conversion_not_supported;
458       break;
459 
460     default:
461       g_assert_not_reached ();
462       break;
463   }
464 
465   return TRUE;
466 
467 conversion_not_supported:
468   GST_ERROR_OBJECT (vc1parse, "stream conversion not implemented yet");
469   return FALSE;
470 }
471 
472 static gboolean
gst_vc1_parse_renegotiate(GstVC1Parse * vc1parse)473 gst_vc1_parse_renegotiate (GstVC1Parse * vc1parse)
474 {
475   GstCaps *in_caps;
476   GstCaps *allowed_caps;
477   GstCaps *tmp;
478 
479   /* Negotiate with downstream here */
480   GST_DEBUG_OBJECT (vc1parse, "Renegotiating");
481 
482   gst_pad_check_reconfigure (GST_BASE_PARSE_SRC_PAD (vc1parse));
483 
484   allowed_caps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (vc1parse));
485   if (allowed_caps && !gst_caps_is_empty (allowed_caps)
486       && !gst_caps_is_any (allowed_caps)) {
487     GstStructure *s;
488     const gchar *stream_format, *header_format;
489 
490     GST_DEBUG_OBJECT (vc1parse, "Downstream allowed caps: %" GST_PTR_FORMAT,
491         allowed_caps);
492 
493     /* Downstream element can have differents caps according to wmv format
494      * so intersect to select the good caps */
495     in_caps = gst_caps_new_simple ("video/x-wmv",
496         "format", G_TYPE_STRING, parse_format_to_string (vc1parse->format),
497         NULL);
498 
499     tmp = gst_caps_intersect_full (allowed_caps, in_caps,
500         GST_CAPS_INTERSECT_FIRST);
501     gst_caps_unref (in_caps);
502 
503     if (gst_caps_is_empty (tmp)) {
504       GST_ERROR_OBJECT (vc1parse, "Empty caps, downstream doesn't support %s",
505           parse_format_to_string (vc1parse->format));
506       gst_caps_unref (tmp);
507       gst_pad_mark_reconfigure (GST_BASE_PARSE_SRC_PAD (vc1parse));
508       return FALSE;
509     }
510 
511     tmp = gst_caps_make_writable (tmp);
512     s = gst_caps_get_structure (tmp, 0);
513 
514     /* If already fixed this does nothing */
515     gst_structure_fixate_field_string (s, "header-format", "asf");
516     header_format = gst_structure_get_string (s, "header-format");
517     if (!header_format) {
518       vc1parse->output_header_format = vc1parse->input_header_format;
519       header_format = header_format_to_string (vc1parse->output_header_format);
520       gst_structure_set (s, "header-format", G_TYPE_STRING, header_format,
521           NULL);
522     } else {
523       vc1parse->output_header_format =
524           header_format_from_string (header_format);
525     }
526 
527     /* If already fixed this does nothing */
528     gst_structure_fixate_field_string (s, "stream-format", "asf");
529     stream_format = gst_structure_get_string (s, "stream-format");
530     if (!stream_format) {
531       vc1parse->output_stream_format = vc1parse->input_stream_format;
532       stream_format = stream_format_to_string (vc1parse->output_stream_format);
533       gst_structure_set (s, "stream-format", G_TYPE_STRING, stream_format,
534           NULL);
535     } else {
536       vc1parse->output_stream_format =
537           stream_format_from_string (stream_format);
538     }
539     gst_caps_unref (tmp);
540   } else if (gst_caps_is_empty (allowed_caps)) {
541     GST_ERROR_OBJECT (vc1parse, "Empty caps");
542     gst_caps_unref (allowed_caps);
543     gst_pad_mark_reconfigure (GST_BASE_PARSE_SRC_PAD (vc1parse));
544     return FALSE;
545   } else {
546     GST_DEBUG_OBJECT (vc1parse, "Using input header/stream format");
547     vc1parse->output_header_format = vc1parse->input_header_format;
548     vc1parse->output_stream_format = vc1parse->input_stream_format;
549   }
550 
551   if (allowed_caps)
552     gst_caps_unref (allowed_caps);
553 
554   if (!gst_vc1_parse_is_format_allowed (vc1parse)) {
555     gst_pad_mark_reconfigure (GST_BASE_PARSE_SRC_PAD (vc1parse));
556     return FALSE;
557   }
558 
559   vc1parse->renegotiate = FALSE;
560   vc1parse->update_caps = TRUE;
561 
562   GST_INFO_OBJECT (vc1parse, "input %s/%s, negotiated %s/%s with downstream",
563       header_format_to_string (vc1parse->input_header_format),
564       stream_format_to_string (vc1parse->input_stream_format),
565       header_format_to_string (vc1parse->output_header_format),
566       stream_format_to_string (vc1parse->output_stream_format));
567 
568   return TRUE;
569 }
570 
571 static void
remove_fields(GstCaps * caps)572 remove_fields (GstCaps * caps)
573 {
574   guint i, n;
575 
576   n = gst_caps_get_size (caps);
577   for (i = 0; i < n; i++) {
578     GstStructure *s = gst_caps_get_structure (caps, i);
579 
580     gst_structure_remove_field (s, "stream-format");
581     gst_structure_remove_field (s, "header-format");
582   }
583 }
584 
585 static GstCaps *
gst_vc1_parse_get_sink_caps(GstBaseParse * parse,GstCaps * filter)586 gst_vc1_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter)
587 {
588   GstCaps *peercaps;
589   GstCaps *templ;
590   GstCaps *ret;
591 
592   templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
593   if (filter) {
594     GstCaps *fcopy = gst_caps_copy (filter);
595     /* Remove the fields we convert */
596     remove_fields (fcopy);
597     peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
598     gst_caps_unref (fcopy);
599   } else
600     peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
601 
602   if (peercaps) {
603     /* Remove the stream-format and header-format fields
604      * and add the generic ones again by intersecting
605      * with our template */
606     peercaps = gst_caps_make_writable (peercaps);
607     remove_fields (peercaps);
608 
609     ret = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
610     gst_caps_unref (peercaps);
611     gst_caps_unref (templ);
612   } else {
613     ret = templ;
614   }
615 
616   if (filter) {
617     GstCaps *tmp =
618         gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
619     gst_caps_unref (ret);
620     ret = tmp;
621   }
622 
623   return ret;
624 }
625 
626 static GstFlowReturn
gst_vc1_parse_detect(GstBaseParse * parse,GstBuffer * buffer)627 gst_vc1_parse_detect (GstBaseParse * parse, GstBuffer * buffer)
628 {
629   GstVC1Parse *vc1parse = GST_VC1_PARSE (parse);
630   GstMapInfo minfo;
631   guint8 *data;
632   gint size;
633 
634   if (!vc1parse->detecting_stream_format)
635     return GST_FLOW_OK;
636 
637   if (!gst_buffer_map (buffer, &minfo, GST_MAP_READ))
638     return GST_FLOW_ERROR;
639 
640   data = minfo.data;
641   size = minfo.size;
642 
643 #if 0
644   /* FIXME: disable BDU check for now as BDU parsing needs more work.
645    */
646   while (size >= 4) {
647     guint32 startcode = GST_READ_UINT32_BE (data);
648 
649     if ((startcode & 0xffffff00) == 0x00000100) {
650       GST_DEBUG_OBJECT (vc1parse, "Found BDU startcode");
651       vc1parse->input_stream_format = VC1_STREAM_FORMAT_BDU_FRAME;
652       goto detected;
653     }
654 
655     data += 4;
656     size -= 4;
657   }
658 #endif
659 
660   while (size >= 40) {
661     if (data[3] == 0xc5 && GST_READ_UINT32_LE (data + 4) == 0x00000004 &&
662         GST_READ_UINT32_LE (data + 20) == 0x0000000c) {
663       guint32 startcode;
664 
665       GST_DEBUG_OBJECT (vc1parse, "Found sequence layer");
666       startcode = GST_READ_UINT32_BE (data + 36);
667       if ((startcode & 0xffffff00) == 0x00000100) {
668         GST_DEBUG_OBJECT (vc1parse, "Found BDU startcode after sequence layer");
669         vc1parse->input_stream_format =
670             VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME;
671         goto detected;
672       } else {
673         GST_DEBUG_OBJECT (vc1parse,
674             "Assuming sequence-layer-frame-layer stream format");
675         vc1parse->input_stream_format =
676             VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER;
677         goto detected;
678       }
679     }
680     data += 4;
681     size -= 4;
682   }
683 
684   if (gst_buffer_get_size (buffer) <= 128) {
685     GST_DEBUG_OBJECT (vc1parse, "Requesting more data");
686     gst_buffer_unmap (buffer, &minfo);
687     return GST_FLOW_NOT_NEGOTIATED;
688   }
689 
690   if (GST_BASE_PARSE_DRAINING (vc1parse)) {
691     GST_ERROR_OBJECT (vc1parse, "Failed to detect or assume a stream format "
692         "and draining now");
693     gst_buffer_unmap (buffer, &minfo);
694     return GST_FLOW_ERROR;
695   }
696 
697   /* Otherwise we try some heuristics */
698   if (vc1parse->input_header_format == VC1_HEADER_FORMAT_ASF) {
699     GST_DEBUG_OBJECT (vc1parse, "Assuming ASF stream format");
700     vc1parse->input_stream_format = VC1_STREAM_FORMAT_ASF;
701     goto detected;
702   } else if (vc1parse->input_header_format == VC1_HEADER_FORMAT_SEQUENCE_LAYER) {
703     GST_DEBUG_OBJECT (vc1parse, "Assuming frame-layer stream format");
704     vc1parse->input_stream_format = VC1_STREAM_FORMAT_FRAME_LAYER;
705     goto detected;
706   } else {
707     GST_ERROR_OBJECT (vc1parse, "Can't detect or assume a stream format");
708     gst_buffer_unmap (buffer, &minfo);
709     return GST_FLOW_ERROR;
710   }
711 
712   g_assert_not_reached ();
713   return GST_FLOW_ERROR;
714 
715 detected:
716 
717   gst_buffer_unmap (buffer, &minfo);
718   vc1parse->detecting_stream_format = FALSE;
719   gst_vc1_parse_update_stream_format_properties (vc1parse);
720   return GST_FLOW_OK;
721 }
722 
723 static int
gst_vc1_parse_get_max_framerate(GstVC1Parse * vc1parse)724 gst_vc1_parse_get_max_framerate (GstVC1Parse * vc1parse)
725 {
726   /* http://wiki.multimedia.cx/index.php?title=VC-1#Setup_Data_.2F_Sequence_Layer */
727   switch (vc1parse->profile) {
728     case GST_VC1_PROFILE_SIMPLE:
729       switch (vc1parse->level) {
730         case GST_VC1_LEVEL_LOW:
731           return 15;
732         case GST_VC1_LEVEL_MEDIUM:
733           return 30;
734         default:
735           g_assert_not_reached ();
736           return 0;
737       }
738       break;
739     case GST_VC1_PROFILE_MAIN:
740       switch (vc1parse->level) {
741         case GST_VC1_LEVEL_LOW:
742           return 24;
743         case GST_VC1_LEVEL_MEDIUM:
744           return 30;
745         case GST_VC1_LEVEL_HIGH:
746           return 30;
747         default:
748           g_assert_not_reached ();
749           return 0;
750       }
751       break;
752     case GST_VC1_PROFILE_ADVANCED:
753       switch (vc1parse->level) {
754         case GST_VC1_LEVEL_L0:
755           return 30;
756         case GST_VC1_LEVEL_L1:
757           return 30;
758         case GST_VC1_LEVEL_L2:
759           return 60;
760         case GST_VC1_LEVEL_L3:
761           return 60;
762         case GST_VC1_LEVEL_L4:
763           return 60;
764         default:
765           g_assert_not_reached ();
766           return 0;
767       }
768       break;
769     default:
770       g_assert_not_reached ();
771       return 0;
772   }
773 }
774 
775 static GstBuffer *
gst_vc1_parse_make_sequence_layer(GstVC1Parse * vc1parse)776 gst_vc1_parse_make_sequence_layer (GstVC1Parse * vc1parse)
777 {
778   GstBuffer *seq_layer_buffer;
779   guint8 *data;
780   guint32 structC = 0;
781   GstMapInfo minfo;
782 
783   seq_layer_buffer = gst_buffer_new_and_alloc (36);
784   gst_buffer_map (seq_layer_buffer, &minfo, GST_MAP_WRITE);
785 
786   data = minfo.data;
787   /* According to SMPTE 421M Annex L, the sequence layer shall be
788    * represented as a sequence of 32 bit unsigned integers and each
789    * integers should be serialized in little-endian byte-order except for
790    * STRUCT_C which should be serialized in big-endian byte-order. */
791 
792   /* Unknown number of frames and start code */
793   data[0] = 0xff;
794   data[1] = 0xff;
795   data[2] = 0xff;
796   data[3] = 0xc5;
797 
798   /* 0x00000004 */
799   GST_WRITE_UINT32_LE (data + 4, 4);
800 
801   /* structC */
802   structC |= (vc1parse->profile << 30);
803   if (vc1parse->profile != GST_VC1_PROFILE_ADVANCED) {
804     /* Build simple/main structC from sequence header */
805     structC |= (vc1parse->seq_hdr.struct_c.wmvp << 28);
806     structC |= (vc1parse->seq_hdr.struct_c.frmrtq_postproc << 25);
807     structC |= (vc1parse->seq_hdr.struct_c.bitrtq_postproc << 20);
808     structC |= (vc1parse->seq_hdr.struct_c.loop_filter << 19);
809     /* Reserved3 shall be set to zero */
810     structC |= (vc1parse->seq_hdr.struct_c.multires << 17);
811     /* Reserved4 shall be set to one */
812     structC |= (1 << 16);
813     structC |= (vc1parse->seq_hdr.struct_c.fastuvmc << 15);
814     structC |= (vc1parse->seq_hdr.struct_c.extended_mv << 14);
815     structC |= (vc1parse->seq_hdr.struct_c.dquant << 12);
816     structC |= (vc1parse->seq_hdr.struct_c.vstransform << 11);
817     /* Reserved5 shall be set to zero */
818     structC |= (vc1parse->seq_hdr.struct_c.overlap << 9);
819     structC |= (vc1parse->seq_hdr.struct_c.syncmarker << 8);
820     structC |= (vc1parse->seq_hdr.struct_c.rangered << 7);
821     structC |= (vc1parse->seq_hdr.struct_c.maxbframes << 4);
822     structC |= (vc1parse->seq_hdr.struct_c.quantizer << 2);
823     structC |= (vc1parse->seq_hdr.struct_c.finterpflag << 1);
824     /* Reserved6 shall be set to one */
825     structC |= 1;
826   }
827   GST_WRITE_UINT32_BE (data + 8, structC);
828 
829   /* structA */
830   if (vc1parse->profile != GST_VC1_PROFILE_ADVANCED) {
831     GST_WRITE_UINT32_LE (data + 12, vc1parse->height);
832     GST_WRITE_UINT32_LE (data + 16, vc1parse->width);
833   } else {
834     GST_WRITE_UINT32_LE (data + 12, 0);
835     GST_WRITE_UINT32_LE (data + 16, 0);
836   }
837 
838   /* 0x0000000c */
839   GST_WRITE_UINT32_LE (data + 20, 0x0000000c);
840 
841   /* structB */
842   /* Unknown HRD_BUFFER */
843   GST_WRITE_UINT24_LE (data + 24, 0);
844   if ((gint) vc1parse->level != -1)
845     data[27] = (vc1parse->level << 5);
846   else
847     data[27] = (0x4 << 5);      /* Use HIGH level */
848   /* Unknown HRD_RATE */
849   GST_WRITE_UINT32_LE (data + 28, 0);
850   /* Framerate */
851   if (vc1parse->fps_d == 0) {
852     /* If not known, it seems we need to put in the maximum framerate
853        possible for the profile/level used (this is for RTP
854        (https://tools.ietf.org/html/draft-ietf-avt-rtp-vc1-06#section-6.1),
855        so likely elsewhere too */
856     GST_WRITE_UINT32_LE (data + 32, gst_vc1_parse_get_max_framerate (vc1parse));
857   } else {
858     GST_WRITE_UINT32_LE (data + 32,
859         ((guint32) (((gdouble) vc1parse->fps_n) /
860                 ((gdouble) vc1parse->fps_d) + 0.5)));
861   }
862 
863   gst_buffer_unmap (seq_layer_buffer, &minfo);
864 
865   return seq_layer_buffer;
866 }
867 
868 static gboolean
gst_vc1_parse_update_caps(GstVC1Parse * vc1parse)869 gst_vc1_parse_update_caps (GstVC1Parse * vc1parse)
870 {
871   GstCaps *caps;
872   GstVC1Profile profile = -1;
873   const gchar *stream_format, *header_format;
874 
875   if (gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (vc1parse))
876       && !vc1parse->update_caps)
877     return TRUE;
878 
879   caps = gst_caps_new_simple ("video/x-wmv", "wmvversion", G_TYPE_INT, 3, NULL);
880 
881   header_format = header_format_to_string (vc1parse->output_header_format);
882   stream_format = stream_format_to_string (vc1parse->output_stream_format);
883   gst_caps_set_simple (caps, "header-format", G_TYPE_STRING, header_format,
884       "stream-format", G_TYPE_STRING, stream_format, NULL);
885 
886   /* Must have this here from somewhere */
887   g_assert (vc1parse->width != 0 && vc1parse->height != 0);
888   gst_caps_set_simple (caps, "width", G_TYPE_INT, vc1parse->width, "height",
889       G_TYPE_INT, vc1parse->height, NULL);
890   if (vc1parse->fps_d != 0) {
891     gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, vc1parse->fps_n,
892         vc1parse->fps_d, NULL);
893 
894     vc1parse->frame_duration = gst_util_uint64_scale (GST_SECOND,
895         vc1parse->fps_d, vc1parse->fps_n);
896   }
897 
898   if (vc1parse->par_n != 0 && vc1parse->par_d != 0)
899     gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
900         vc1parse->par_n, vc1parse->par_d, NULL);
901 
902   if (vc1parse->seq_hdr_buffer)
903     profile = vc1parse->seq_hdr.profile;
904   else if (vc1parse->seq_layer_buffer)
905     profile = vc1parse->seq_layer.struct_c.profile;
906   else
907     g_assert_not_reached ();
908 
909   if (profile == GST_VC1_PROFILE_ADVANCED) {
910     const gchar *level = NULL;
911     /* Caller must make sure this is valid here */
912     g_assert (vc1parse->seq_hdr_buffer);
913     switch ((GstVC1Level) vc1parse->seq_hdr.advanced.level) {
914       case GST_VC1_LEVEL_L0:
915         level = "0";
916         break;
917       case GST_VC1_LEVEL_L1:
918         level = "1";
919         break;
920       case GST_VC1_LEVEL_L2:
921         level = "2";
922         break;
923       case GST_VC1_LEVEL_L3:
924         level = "3";
925         break;
926       case GST_VC1_LEVEL_L4:
927         level = "4";
928         break;
929       default:
930         g_assert_not_reached ();
931         break;
932     }
933 
934     gst_caps_set_simple (caps, "format", G_TYPE_STRING, "WVC1",
935         "profile", G_TYPE_STRING, "advanced",
936         "level", G_TYPE_STRING, level, NULL);
937   } else if (profile == GST_VC1_PROFILE_SIMPLE
938       || profile == GST_VC1_PROFILE_MAIN) {
939     const gchar *profile_str;
940 
941     if (profile == GST_VC1_PROFILE_SIMPLE)
942       profile_str = "simple";
943     else
944       profile_str = "main";
945 
946     gst_caps_set_simple (caps, "format", G_TYPE_STRING, "WMV3",
947         "profile", G_TYPE_STRING, profile_str, NULL);
948 
949     if (vc1parse->seq_layer_buffer) {
950       const gchar *level = NULL;
951       switch (vc1parse->seq_layer.struct_b.level) {
952         case GST_VC1_LEVEL_LOW:
953           level = "low";
954           break;
955         case GST_VC1_LEVEL_MEDIUM:
956           level = "medium";
957           break;
958         case GST_VC1_LEVEL_HIGH:
959           level = "high";
960           break;
961         default:
962           g_assert_not_reached ();
963           break;
964       }
965 
966       gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
967     }
968   } else {
969     g_assert_not_reached ();
970   }
971 
972   switch (vc1parse->output_header_format) {
973     case VC1_HEADER_FORMAT_ASF:
974       if (vc1parse->profile != GST_VC1_PROFILE_ADVANCED) {
975         GstBuffer *codec_data;
976 
977         if (vc1parse->seq_hdr_buffer) {
978           codec_data =
979               gst_buffer_copy_region (vc1parse->seq_hdr_buffer,
980               GST_BUFFER_COPY_ALL, 0, 4);
981         } else {
982           GstMapInfo minfo;
983           guint32 seq_hdr = 0;
984 
985           /* Build simple/main sequence header from sequence layer */
986           seq_hdr |= (vc1parse->profile << 30);
987           seq_hdr |= (vc1parse->seq_layer.struct_c.wmvp << 28);
988           seq_hdr |= (vc1parse->seq_layer.struct_c.frmrtq_postproc << 25);
989           seq_hdr |= (vc1parse->seq_layer.struct_c.bitrtq_postproc << 20);
990           seq_hdr |= (vc1parse->seq_layer.struct_c.loop_filter << 19);
991           /* Reserved3 shall be set to zero */
992           seq_hdr |= (vc1parse->seq_layer.struct_c.multires << 17);
993           /* Reserved4 shall be set to one */
994           seq_hdr |= (1 << 16);
995           seq_hdr |= (vc1parse->seq_layer.struct_c.fastuvmc << 15);
996           seq_hdr |= (vc1parse->seq_layer.struct_c.extended_mv << 14);
997           seq_hdr |= (vc1parse->seq_layer.struct_c.dquant << 12);
998           seq_hdr |= (vc1parse->seq_layer.struct_c.vstransform << 11);
999           /* Reserved5 shall be set to zero */
1000           seq_hdr |= (vc1parse->seq_layer.struct_c.overlap << 9);
1001           seq_hdr |= (vc1parse->seq_layer.struct_c.syncmarker << 8);
1002           seq_hdr |= (vc1parse->seq_layer.struct_c.rangered << 7);
1003           seq_hdr |= (vc1parse->seq_layer.struct_c.maxbframes << 4);
1004           seq_hdr |= (vc1parse->seq_layer.struct_c.quantizer << 2);
1005           seq_hdr |= (vc1parse->seq_layer.struct_c.finterpflag << 1);
1006           /* Reserved6 shall be set to one */
1007           seq_hdr |= 1;
1008           codec_data = gst_buffer_new_and_alloc (4);
1009 
1010           gst_buffer_map (codec_data, &minfo, GST_MAP_WRITE);
1011           GST_WRITE_UINT32_BE (minfo.data, seq_hdr);
1012           gst_buffer_unmap (codec_data, &minfo);
1013         }
1014 
1015         gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_data,
1016             NULL);
1017         gst_buffer_unref (codec_data);
1018       } else {
1019         GstBuffer *codec_data;
1020         GstMapInfo minfo, sminfo, eminfo;
1021 
1022         /* Should have seqhdr and entrypoint for the advanced profile here */
1023         g_assert (vc1parse->seq_hdr_buffer && vc1parse->entrypoint_buffer);
1024         codec_data =
1025             gst_buffer_new_and_alloc (1 + 4 +
1026             gst_buffer_get_size (vc1parse->seq_hdr_buffer) + 4 +
1027             gst_buffer_get_size (vc1parse->entrypoint_buffer));
1028 
1029         gst_buffer_map (codec_data, &minfo, GST_MAP_WRITE);
1030         gst_buffer_map (vc1parse->seq_hdr_buffer, &sminfo, GST_MAP_READ);
1031         gst_buffer_map (vc1parse->entrypoint_buffer, &eminfo, GST_MAP_READ);
1032 
1033         if (vc1parse->profile == GST_VC1_PROFILE_SIMPLE)
1034           GST_WRITE_UINT8 (minfo.data, 0x29);
1035         else
1036           GST_WRITE_UINT8 (minfo.data, 0x2b);
1037 
1038         GST_WRITE_UINT32_BE (minfo.data + 1, 0x0000010f);
1039         memcpy (minfo.data + 1 + 4, sminfo.data, sminfo.size);
1040         GST_WRITE_UINT32_BE (minfo.data + 1 + 4 +
1041             gst_buffer_get_size (vc1parse->seq_hdr_buffer), 0x0000010e);
1042         memcpy (minfo.data + 1 + 4 + sminfo.size + 4, eminfo.data, eminfo.size);
1043         gst_buffer_unmap (codec_data, &minfo);
1044         gst_buffer_unmap (vc1parse->seq_hdr_buffer, &sminfo);
1045         gst_buffer_unmap (vc1parse->entrypoint_buffer, &eminfo);
1046 
1047         gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_data,
1048             NULL);
1049         gst_buffer_unref (codec_data);
1050       }
1051       break;
1052     case VC1_HEADER_FORMAT_SEQUENCE_LAYER:
1053       if (vc1parse->seq_layer_buffer) {
1054         gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
1055             vc1parse->seq_layer_buffer, NULL);
1056       } else {
1057         GstBuffer *codec_data;
1058 
1059         codec_data = gst_vc1_parse_make_sequence_layer (vc1parse);
1060 
1061         gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_data,
1062             NULL);
1063         gst_buffer_unref (codec_data);
1064       }
1065       break;
1066     case VC1_HEADER_FORMAT_NONE:
1067     default:
1068       /* Nothing here */
1069       break;
1070   }
1071 
1072   GST_DEBUG_OBJECT (vc1parse, "Setting caps %" GST_PTR_FORMAT, caps);
1073   gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (vc1parse), caps);
1074   gst_caps_unref (caps);
1075   vc1parse->update_caps = FALSE;
1076   return TRUE;
1077 }
1078 
1079 static inline void
calculate_mb_size(GstVC1SeqHdr * seqhdr,guint width,guint height)1080 calculate_mb_size (GstVC1SeqHdr * seqhdr, guint width, guint height)
1081 {
1082   seqhdr->mb_width = (width + 15) >> 4;
1083   seqhdr->mb_height = (height + 15) >> 4;
1084   seqhdr->mb_stride = seqhdr->mb_width + 1;
1085 }
1086 
1087 static gboolean
gst_vc1_parse_handle_bdu(GstVC1Parse * vc1parse,GstVC1StartCode startcode,GstBuffer * buffer,guint offset,guint size)1088 gst_vc1_parse_handle_bdu (GstVC1Parse * vc1parse, GstVC1StartCode startcode,
1089     GstBuffer * buffer, guint offset, guint size)
1090 {
1091   GST_DEBUG_OBJECT (vc1parse, "Handling BDU with startcode 0x%02x", startcode);
1092 
1093   switch (startcode) {
1094     case GST_VC1_SEQUENCE:{
1095       GST_DEBUG_OBJECT (vc1parse, "Have new SequenceHeader header");
1096       if (!gst_vc1_parse_handle_seq_hdr (vc1parse, buffer, offset, size)) {
1097         GST_ERROR_OBJECT (vc1parse, "Invalid VC1 sequence header");
1098         return FALSE;
1099       }
1100       break;
1101     }
1102     case GST_VC1_ENTRYPOINT:
1103       GST_DEBUG_OBJECT (vc1parse, "Have new EntryPoint header");
1104       if (!gst_vc1_parse_handle_entrypoint (vc1parse, buffer, offset, size)) {
1105         GST_ERROR_OBJECT (vc1parse, "Invalid VC1 entrypoint");
1106         return FALSE;
1107       }
1108       break;
1109     case GST_VC1_FRAME:
1110       /* TODO: Check if keyframe */
1111       break;
1112     default:
1113       break;
1114   }
1115 
1116   return TRUE;
1117 }
1118 
1119 static gboolean
gst_vc1_parse_handle_bdus(GstVC1Parse * vc1parse,GstBuffer * buffer,guint offset,guint size)1120 gst_vc1_parse_handle_bdus (GstVC1Parse * vc1parse, GstBuffer * buffer,
1121     guint offset, guint size)
1122 {
1123   GstVC1BDU bdu;
1124   GstVC1ParserResult pres;
1125   guint8 *data;
1126   GstMapInfo minfo;
1127 
1128   gst_buffer_map (buffer, &minfo, GST_MAP_READ);
1129 
1130   data = minfo.data + offset;
1131 
1132   do {
1133     memset (&bdu, 0, sizeof (bdu));
1134     pres = gst_vc1_identify_next_bdu (data, size, &bdu);
1135     if (pres == GST_VC1_PARSER_OK || pres == GST_VC1_PARSER_NO_BDU_END) {
1136       if (pres == GST_VC1_PARSER_NO_BDU_END) {
1137         pres = GST_VC1_PARSER_OK;
1138         bdu.size = size - bdu.offset;
1139       }
1140 
1141       data += bdu.offset;
1142       size -= bdu.offset;
1143 
1144       if (!gst_vc1_parse_handle_bdu (vc1parse, bdu.type, buffer,
1145               data - minfo.data, bdu.size)) {
1146         gst_buffer_unmap (buffer, &minfo);
1147         return FALSE;
1148       }
1149 
1150       data += bdu.size;
1151       size -= bdu.size;
1152     }
1153   } while (pres == GST_VC1_PARSER_OK && size > 0);
1154 
1155   gst_buffer_unmap (buffer, &minfo);
1156 
1157   if (pres != GST_VC1_PARSER_OK) {
1158     GST_DEBUG_OBJECT (vc1parse, "Failed to parse BDUs");
1159     return FALSE;
1160   }
1161   return TRUE;
1162 }
1163 
1164 static GstFlowReturn
gst_vc1_parse_handle_frame(GstBaseParse * parse,GstBaseParseFrame * frame,gint * skipsize)1165 gst_vc1_parse_handle_frame (GstBaseParse * parse, GstBaseParseFrame * frame,
1166     gint * skipsize)
1167 {
1168   GstVC1Parse *vc1parse = GST_VC1_PARSE (parse);
1169   GstBuffer *buffer = frame->buffer;
1170   guint8 *data;
1171   gsize size;
1172   gsize framesize = -1;
1173   GstFlowReturn ret = GST_FLOW_OK;
1174   GstMapInfo minfo;
1175 
1176   memset (&minfo, 0, sizeof (minfo));
1177 
1178   *skipsize = 0;
1179 
1180   if (vc1parse->renegotiate
1181       || gst_pad_check_reconfigure (GST_BASE_PARSE_SRC_PAD (parse))) {
1182     if (!gst_vc1_parse_renegotiate (vc1parse)) {
1183       GST_ERROR_OBJECT (vc1parse, "Failed to negotiate with downstream");
1184       gst_pad_mark_reconfigure (GST_BASE_PARSE_SRC_PAD (parse));
1185       if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse)))
1186         ret = GST_FLOW_FLUSHING;
1187       else
1188         ret = GST_FLOW_NOT_NEGOTIATED;
1189       goto done;
1190     }
1191   }
1192 
1193   if (!gst_buffer_map (buffer, &minfo, GST_MAP_READ)) {
1194     GST_ERROR_OBJECT (vc1parse, "Failed to map buffer");
1195     ret = GST_FLOW_ERROR;
1196     goto done;
1197   }
1198 
1199   data = minfo.data;
1200   size = minfo.size;
1201 
1202   /* First check if we have a valid, complete frame here */
1203   if (!vc1parse->seq_layer_buffer
1204       && (vc1parse->input_stream_format == VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU
1205           || vc1parse->input_stream_format ==
1206           VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME
1207           || vc1parse->input_stream_format ==
1208           VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME
1209           || vc1parse->input_stream_format ==
1210           VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER)) {
1211     if (data[3] == 0xc5 && GST_READ_UINT32_LE (data + 4) == 0x00000004
1212         && GST_READ_UINT32_LE (data + 20) == 0x0000000c) {
1213       framesize = 36;
1214     } else {
1215       *skipsize = 1;
1216     }
1217   } else if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU ||
1218       vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU_FRAME ||
1219       (vc1parse->seq_layer_buffer
1220           && (vc1parse->input_stream_format ==
1221               VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU
1222               || vc1parse->input_stream_format ==
1223               VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME))) {
1224     GstVC1ParserResult pres;
1225     GstVC1BDU bdu;
1226 
1227     g_assert (size >= 4);
1228     memset (&bdu, 0, sizeof (bdu));
1229     GST_DEBUG_OBJECT (vc1parse,
1230         "Handling buffer of size %" G_GSIZE_FORMAT " at offset %"
1231         G_GUINT64_FORMAT, size, GST_BUFFER_OFFSET (buffer));
1232     /* XXX: when a buffer contains multiple BDUs, does the first one start with
1233      * a startcode?
1234      */
1235     pres = gst_vc1_identify_next_bdu (data, size, &bdu);
1236     switch (pres) {
1237       case GST_VC1_PARSER_OK:
1238         GST_DEBUG_OBJECT (vc1parse, "Have complete BDU");
1239         if (bdu.sc_offset > 4) {
1240           *skipsize = bdu.sc_offset;
1241         } else {
1242           framesize = bdu.offset + bdu.size;
1243         }
1244         break;
1245       case GST_VC1_PARSER_BROKEN_DATA:
1246         GST_ERROR_OBJECT (vc1parse, "Broken data");
1247         *skipsize = 1;
1248         break;
1249       case GST_VC1_PARSER_NO_BDU:
1250         GST_DEBUG_OBJECT (vc1parse, "Found no BDU startcode");
1251         *skipsize = size - 3;
1252         break;
1253       case GST_VC1_PARSER_NO_BDU_END:
1254         GST_DEBUG_OBJECT (vc1parse, "Found no BDU end");
1255         if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (vc1parse))) {
1256           GST_DEBUG_OBJECT (vc1parse, "Draining - assuming complete frame");
1257           framesize = size;
1258         } else {
1259           /* Need more data */
1260           *skipsize = 0;
1261         }
1262         break;
1263       case GST_VC1_PARSER_ERROR:
1264         GST_ERROR_OBJECT (vc1parse, "Parsing error");
1265         break;
1266       default:
1267         g_assert_not_reached ();
1268         break;
1269     }
1270   } else if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_ASF ||
1271       (vc1parse->seq_layer_buffer
1272           && vc1parse->input_stream_format ==
1273           VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME)) {
1274     /* Must be packetized already */
1275     framesize = size;
1276   } else {
1277     /* frame-layer or sequence-layer-frame-layer */
1278     g_assert (size >= 8);
1279     /* Parse frame layer size */
1280     framesize = GST_READ_UINT24_LE (data) + 8;
1281   }
1282 
1283 
1284   if (framesize == -1) {
1285     GST_DEBUG_OBJECT (vc1parse, "Not a complete frame, skipping %d", *skipsize);
1286     ret = GST_FLOW_OK;
1287     goto done;
1288   }
1289   g_assert (*skipsize == 0);
1290 
1291   /* We have a complete frame at this point */
1292 
1293   if (!vc1parse->seq_layer_buffer
1294       && (vc1parse->input_stream_format == VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU
1295           || vc1parse->input_stream_format ==
1296           VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME
1297           || vc1parse->input_stream_format ==
1298           VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME
1299           || vc1parse->input_stream_format ==
1300           VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER)) {
1301     g_assert (size >= 36);
1302     if (!gst_vc1_parse_handle_seq_layer (vc1parse, buffer, 0, size)) {
1303       GST_ERROR_OBJECT (vc1parse, "Invalid sequence layer");
1304       ret = GST_FLOW_ERROR;
1305       goto done;
1306     }
1307 
1308     frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NO_FRAME;
1309 
1310     if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU
1311         || vc1parse->input_stream_format ==
1312         VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME) {
1313       gst_base_parse_set_min_frame_size (GST_BASE_PARSE (vc1parse), 4);
1314     } else if (vc1parse->input_stream_format ==
1315         VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME) {
1316       gst_base_parse_set_min_frame_size (GST_BASE_PARSE (vc1parse), 1);
1317     } else {
1318       /* frame-layer */
1319       gst_base_parse_set_min_frame_size (GST_BASE_PARSE (vc1parse), 8);
1320     }
1321   } else if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU ||
1322       vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU_FRAME ||
1323       (vc1parse->seq_layer_buffer
1324           && (vc1parse->input_stream_format ==
1325               VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU
1326               || vc1parse->input_stream_format ==
1327               VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME))) {
1328     GstVC1StartCode startcode;
1329 
1330     /* Is already a complete BDU, should have at least the startcode */
1331     g_assert (size >= 4);
1332     startcode = data[3];
1333 
1334     if (startcode != GST_VC1_SEQUENCE) {
1335       if (!vc1parse->seq_hdr_buffer && !vc1parse->seq_layer_buffer) {
1336         GST_ERROR_OBJECT (vc1parse,
1337             "Need sequence header/layer before anything else");
1338         ret = GST_FLOW_ERROR;
1339         goto done;
1340       }
1341     } else if (startcode != GST_VC1_ENTRYPOINT
1342         && vc1parse->profile == GST_VC1_PROFILE_ADVANCED) {
1343       if (vc1parse->seq_hdr_buffer && !vc1parse->entrypoint_buffer) {
1344         GST_ERROR_OBJECT (vc1parse,
1345             "Need entrypoint header after the sequence header for the "
1346             "advanced profile");
1347         ret = GST_FLOW_ERROR;
1348         goto done;
1349       }
1350     }
1351 
1352     if (!gst_vc1_parse_handle_bdu (vc1parse, startcode, buffer, 4, size - 4)) {
1353       ret = GST_FLOW_ERROR;
1354       goto done;
1355     }
1356   } else if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_ASF ||
1357       (vc1parse->seq_layer_buffer
1358           && vc1parse->input_stream_format ==
1359           VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME)) {
1360     GST_LOG_OBJECT (vc1parse, "Have new ASF or RAW data unit");
1361 
1362     if (!vc1parse->seq_hdr_buffer && !vc1parse->seq_layer_buffer) {
1363       GST_ERROR_OBJECT (vc1parse, "Need a sequence header or sequence layer");
1364       ret = GST_FLOW_ERROR;
1365       goto done;
1366     }
1367 
1368     if (GST_CLOCK_TIME_IS_VALID (vc1parse->frame_duration))
1369       GST_BUFFER_DURATION (buffer) = vc1parse->frame_duration;
1370 
1371     /* Might be multiple BDUs here, complex... */
1372     if (vc1parse->profile == GST_VC1_PROFILE_ADVANCED) {
1373       gboolean startcodes = FALSE;
1374 
1375       if (size >= 4) {
1376         guint32 startcode = GST_READ_UINT32_BE (data + 4);
1377 
1378         startcodes = ((startcode & 0xffffff00) == 0x00000100);
1379       }
1380 
1381       if (startcodes) {
1382         if (!gst_vc1_parse_handle_bdus (vc1parse, buffer, 0, size)) {
1383           ret = GST_FLOW_ERROR;
1384           goto done;
1385         }
1386 
1387         /* For the advanced profile we need a sequence header here */
1388         if (!vc1parse->seq_hdr_buffer) {
1389           GST_ERROR_OBJECT (vc1parse, "Need sequence header");
1390           ret = GST_FLOW_ERROR;
1391           goto done;
1392         }
1393       } else {
1394         /* Must be a frame or a frame + field */
1395         /* TODO: Check if keyframe */
1396       }
1397     } else {
1398       /* In simple/main, we basically have a raw frame, so parse it */
1399       GstVC1ParserResult pres;
1400       GstVC1FrameHdr frame_hdr;
1401       GstVC1SeqHdr seq_hdr;
1402 
1403       if (!vc1parse->seq_hdr_buffer) {
1404         /* Build seq_hdr from sequence-layer to be able to parse frame */
1405         seq_hdr.profile = vc1parse->profile;
1406         seq_hdr.struct_c = vc1parse->seq_layer.struct_c;
1407         calculate_mb_size (&seq_hdr, vc1parse->seq_layer.struct_a.horiz_size,
1408             vc1parse->seq_layer.struct_a.vert_size);
1409       } else {
1410         seq_hdr = vc1parse->seq_hdr;
1411       }
1412 
1413       pres = gst_vc1_parse_frame_header (data, size, &frame_hdr,
1414           &seq_hdr, NULL);
1415       if (pres != GST_VC1_PARSER_OK) {
1416         GST_ERROR_OBJECT (vc1parse, "Invalid VC1 frame header");
1417         ret = GST_FLOW_ERROR;
1418         goto done;
1419       }
1420 
1421       if (frame_hdr.ptype == GST_VC1_PICTURE_TYPE_I)
1422         GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
1423       else
1424         GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
1425     }
1426   } else {
1427     GstVC1ParserResult pres;
1428     GstVC1FrameLayer flayer;
1429     gboolean startcodes = FALSE;
1430 
1431     /* frame-layer or sequence-layer-frame-layer */
1432 
1433     /* Check if the frame-layer data contains BDUs with startcodes.
1434      * Startcodes are not allowed in raw WMV9/VC1 streams
1435      */
1436     if (size >= 8 + 4) {
1437       guint32 startcode = GST_READ_UINT32_BE (data + 8);
1438 
1439       startcodes = ((startcode & 0xffffff00) == 0x00000100);
1440     }
1441 
1442     /* We either need a sequence layer or sequence header here
1443      * or this has to be an advanced profile stream.
1444      *
1445      * For the advanced profile the frame-layer data contains
1446      * BDUs with startcodes and includes the sequence header
1447      */
1448     if (!vc1parse->seq_layer_buffer && !vc1parse->seq_hdr_buffer && !startcodes) {
1449       GST_ERROR_OBJECT (vc1parse, "Need a sequence header or sequence layer");
1450       ret = GST_FLOW_ERROR;
1451       goto done;
1452     }
1453 
1454     if ((vc1parse->seq_layer_buffer || vc1parse->seq_hdr_buffer)
1455         && vc1parse->profile == GST_VC1_PROFILE_ADVANCED && !startcodes) {
1456       GST_ERROR_OBJECT (vc1parse,
1457           "Advanced profile frame-layer data must start with startcodes");
1458       ret = GST_FLOW_ERROR;
1459       goto done;
1460     }
1461 
1462     memset (&flayer, 0, sizeof (flayer));
1463 
1464     pres = gst_vc1_parse_frame_layer (data, size, &flayer);
1465 
1466     if (pres != GST_VC1_PARSER_OK) {
1467       GST_ERROR_OBJECT (vc1parse, "Invalid VC1 frame layer");
1468       ret = GST_FLOW_ERROR;
1469       goto done;
1470     }
1471 
1472     GST_BUFFER_TIMESTAMP (buffer) =
1473         gst_util_uint64_scale (flayer.timestamp, GST_MSECOND, 1);
1474     if (!flayer.key)
1475       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
1476     else
1477       GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
1478 
1479     /* For the simple/main profile this contains a single frame BDU without
1480      * startcodes and for the advanced profile this contains BDUs with
1481      * startcodes. In the case of the advanced profile parse them.
1482      *
1483      * Also for wrongly muxed simple/main profile streams with startcodes
1484      * we do the same.
1485      */
1486     if (startcodes) {
1487       /* skip frame layer header */
1488       if (!gst_vc1_parse_handle_bdus (vc1parse, buffer, 8, size - 8)) {
1489         ret = GST_FLOW_ERROR;
1490         goto done;
1491       }
1492 
1493       /* For the advanced profile we need a sequence header here */
1494       if (!vc1parse->seq_hdr_buffer) {
1495         GST_ERROR_OBJECT (vc1parse, "Need sequence header");
1496         ret = GST_FLOW_ERROR;
1497         goto done;
1498       }
1499     }
1500   }
1501 
1502   /* Need sequence header or sequence layer here, above code
1503    * checks this already */
1504   g_assert (vc1parse->seq_layer_buffer || vc1parse->seq_hdr_buffer);
1505 
1506   /* We need the entrypoint BDU for the advanced profile before we can set
1507    * the caps. For the ASF header format it will already be in the codec_data,
1508    * for the frame-layer stream format it will be in the first frame already.
1509    *
1510    * The only case where we wait another frame is the raw stream format, where
1511    * it will be the second BDU
1512    */
1513   if (vc1parse->profile == GST_VC1_PROFILE_ADVANCED
1514       && !vc1parse->entrypoint_buffer) {
1515     if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU
1516         || vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU_FRAME
1517         || vc1parse->input_stream_format == VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU
1518         || vc1parse->input_stream_format ==
1519         VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME) {
1520       frame->flags |= GST_BASE_PARSE_FRAME_FLAG_QUEUE;
1521     } else {
1522       GST_ERROR_OBJECT (vc1parse, "Need entrypoint for the advanced profile");
1523       ret = GST_FLOW_ERROR;
1524       goto done;
1525     }
1526   }
1527 
1528   if (!gst_vc1_parse_update_caps (vc1parse)) {
1529     ret = GST_FLOW_NOT_NEGOTIATED;
1530     goto done;
1531   }
1532 
1533   gst_buffer_unmap (buffer, &minfo);
1534   memset (&minfo, 0, sizeof (minfo));
1535   GST_DEBUG_OBJECT (vc1parse, "Finishing frame of size %" G_GSIZE_FORMAT,
1536       framesize);
1537   ret = gst_base_parse_finish_frame (parse, frame, framesize);
1538 
1539 done:
1540   if (minfo.data)
1541     gst_buffer_unmap (buffer, &minfo);
1542 
1543   return ret;
1544 }
1545 
1546 static GstFlowReturn
gst_vc1_parse_push_sequence_layer(GstVC1Parse * vc1parse)1547 gst_vc1_parse_push_sequence_layer (GstVC1Parse * vc1parse)
1548 {
1549   GstBuffer *seq_layer;
1550 
1551   if ((seq_layer = vc1parse->seq_layer_buffer))
1552     gst_buffer_ref (seq_layer);
1553   else
1554     seq_layer = gst_vc1_parse_make_sequence_layer (vc1parse);
1555 
1556   return gst_pad_push (GST_BASE_PARSE_SRC_PAD (vc1parse), seq_layer);
1557 }
1558 
1559 static GstFlowReturn
gst_vc1_parse_convert_asf_to_bdu(GstVC1Parse * vc1parse,GstBaseParseFrame * frame)1560 gst_vc1_parse_convert_asf_to_bdu (GstVC1Parse * vc1parse,
1561     GstBaseParseFrame * frame)
1562 {
1563   GstByteWriter bw;
1564   GstBuffer *buffer;
1565   GstBuffer *tmp;
1566   GstMemory *mem;
1567   guint8 sc_data[4];
1568   guint32 startcode;
1569   gboolean ok;
1570   GstFlowReturn ret = GST_FLOW_OK;
1571 
1572   buffer = frame->buffer;
1573 
1574   /* Simple profile doesn't have start codes so bdu format is not possible */
1575   if (vc1parse->profile == GST_VC1_PROFILE_SIMPLE) {
1576     GST_ERROR_OBJECT (vc1parse, "can't convert to bdu in simple profile");
1577     ret = GST_FLOW_NOT_NEGOTIATED;
1578     goto done;
1579   }
1580 
1581   /* ASF frame could have a start code at the beginning or not. So we first
1582    * check for a start code if we have at least 4 bytes in the buffer. */
1583   if (gst_buffer_extract (buffer, 0, sc_data, 4) == 4) {
1584     startcode = GST_READ_UINT32_BE (sc_data);
1585     if (((startcode & 0xffffff00) == 0x00000100)) {
1586       /* Start code found */
1587       goto done;
1588     }
1589   }
1590 
1591   /* Yes, a frame could be smaller than 4 bytes and valid, for instance
1592    * black video. */
1593 
1594   /* We will prepend 4 bytes to buffer */
1595   gst_byte_writer_init_with_size (&bw, 4, TRUE);
1596 
1597   /* Set start code and suffixe, we assume raw asf data is a frame */
1598   ok = gst_byte_writer_put_uint24_be (&bw, 0x000001);
1599   ok &= gst_byte_writer_put_uint8 (&bw, 0x0D);
1600   tmp = gst_byte_writer_reset_and_get_buffer (&bw);
1601 
1602   /* Prepend startcode buffer to frame buffer */
1603   mem = gst_buffer_get_all_memory (tmp);
1604   gst_buffer_prepend_memory (buffer, mem);
1605   gst_buffer_unref (tmp);
1606 
1607   if (G_UNLIKELY (!ok)) {
1608     GST_ERROR_OBJECT (vc1parse, "convert asf to bdu failed");
1609     ret = GST_FLOW_ERROR;
1610   }
1611 
1612 done:
1613   return ret;
1614 }
1615 
1616 static GstFlowReturn
gst_vc1_parse_convert_to_frame_layer(GstVC1Parse * vc1parse,GstBaseParseFrame * frame)1617 gst_vc1_parse_convert_to_frame_layer (GstVC1Parse * vc1parse,
1618     GstBaseParseFrame * frame)
1619 {
1620   GstByteWriter bw;
1621   GstBuffer *buffer;
1622   GstBuffer *frame_layer;
1623   gsize frame_layer_size;
1624   GstMemory *mem;
1625   gboolean ok;
1626   gboolean keyframe;
1627   guint8 sc_data[4];
1628   guint32 startcode;
1629 
1630   buffer = frame->buffer;
1631   keyframe = !(GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT));
1632 
1633   /* We need 8 bytes for frame-layer header */
1634   frame_layer_size = 8;
1635   if (vc1parse->profile == GST_VC1_PROFILE_ADVANCED) {
1636     if (!vc1parse->frame_layer_first_frame_sent) {
1637       /* First frame should contain sequence-header, entry-point and frame */
1638       frame_layer_size += 4 + gst_buffer_get_size (vc1parse->seq_hdr_buffer)
1639           + 4 + gst_buffer_get_size (vc1parse->entrypoint_buffer) + 4;
1640     } else if (keyframe) {
1641       /* Keyframe should contain entry point */
1642       frame_layer_size += 4 +
1643           gst_buffer_get_size (vc1parse->entrypoint_buffer) + 4;
1644     }
1645   }
1646 
1647   gst_byte_writer_init_with_size (&bw, frame_layer_size, TRUE);
1648 
1649   /* frame-layer header shall be serialized in little-endian byte order */
1650   ok = gst_byte_writer_put_uint24_le (&bw, gst_buffer_get_size (buffer));
1651 
1652   if (keyframe)
1653     ok &= gst_byte_writer_put_uint8 (&bw, 0x80);        /* keyframe */
1654   else
1655     ok &= gst_byte_writer_put_uint8 (&bw, 0x00);
1656 
1657   ok &= gst_byte_writer_put_uint32_le (&bw, GST_BUFFER_PTS (buffer));
1658 
1659   if (vc1parse->profile != GST_VC1_PROFILE_ADVANCED)
1660     goto headers_done;
1661 
1662   if (!vc1parse->frame_layer_first_frame_sent) {
1663     /* Write sequence-header start code, sequence-header entrypoint startcode
1664      * and entrypoint */
1665     ok &= gst_byte_writer_put_uint32_be (&bw, 0x0000010f);
1666     ok &= gst_byte_writer_put_buffer (&bw, vc1parse->seq_hdr_buffer, 0, -1);
1667     ok &= gst_byte_writer_put_uint32_be (&bw, 0x0000010e);
1668     ok &= gst_byte_writer_put_buffer (&bw, vc1parse->entrypoint_buffer, 0, -1);
1669   } else if (keyframe) {
1670     /* Write entrypoint startcode and entrypoint */
1671     ok &= gst_byte_writer_put_uint32_be (&bw, 0x0000010e);
1672     ok &= gst_byte_writer_put_buffer (&bw, vc1parse->entrypoint_buffer, 0, -1);
1673   }
1674 
1675   /* frame can begin with startcode, in this case, don't prepend it */
1676   if (gst_buffer_extract (buffer, 0, sc_data, 4) == 4) {
1677     startcode = GST_READ_UINT32_BE (sc_data);
1678     if (((startcode & 0xffffff00) == 0x00000100)) {
1679       /* Start code found */
1680       goto headers_done;
1681     }
1682   }
1683 
1684   ok &= gst_byte_writer_put_uint32_be (&bw, 0x0000010d);
1685 
1686 headers_done:
1687   frame_layer = gst_byte_writer_reset_and_get_buffer (&bw);
1688   mem = gst_buffer_get_all_memory (frame_layer);
1689   gst_buffer_prepend_memory (buffer, mem);
1690   gst_buffer_unref (frame_layer);
1691 
1692   if (G_UNLIKELY (!ok)) {
1693     GST_ERROR_OBJECT (vc1parse, "failed to convert to frame layer");
1694     return GST_FLOW_ERROR;
1695   }
1696 
1697   vc1parse->frame_layer_first_frame_sent = TRUE;
1698   return GST_FLOW_OK;
1699 }
1700 
1701 static GstFlowReturn
gst_vc1_parse_pre_push_frame(GstBaseParse * parse,GstBaseParseFrame * frame)1702 gst_vc1_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1703 {
1704   GstVC1Parse *vc1parse = GST_VC1_PARSE (parse);
1705   GstFlowReturn ret = GST_FLOW_OK;
1706 
1707   if (!vc1parse->sent_codec_tag) {
1708     GstTagList *taglist;
1709     GstCaps *caps;
1710 
1711     /* codec tag */
1712     caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
1713     if (G_UNLIKELY (caps == NULL)) {
1714       if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) {
1715         GST_INFO_OBJECT (parse, "Src pad is flushing");
1716         return GST_FLOW_FLUSHING;
1717       } else {
1718         GST_INFO_OBJECT (parse, "Src pad is not negotiated!");
1719         return GST_FLOW_NOT_NEGOTIATED;
1720       }
1721     }
1722 
1723     taglist = gst_tag_list_new_empty ();
1724     gst_pb_utils_add_codec_description_to_tag_list (taglist,
1725         GST_TAG_VIDEO_CODEC, caps);
1726     gst_caps_unref (caps);
1727 
1728     gst_base_parse_merge_tags (parse, taglist, GST_TAG_MERGE_REPLACE);
1729     gst_tag_list_unref (taglist);
1730 
1731     /* also signals the end of first-frame processing */
1732     vc1parse->sent_codec_tag = TRUE;
1733   }
1734 
1735   /* Nothing to do here */
1736   if (vc1parse->input_stream_format == vc1parse->output_stream_format)
1737     return GST_FLOW_OK;
1738 
1739   switch (vc1parse->output_stream_format) {
1740     case VC1_STREAM_FORMAT_BDU:
1741       switch (vc1parse->input_stream_format) {
1742         case VC1_STREAM_FORMAT_BDU:
1743           g_assert_not_reached ();
1744           break;
1745         case VC1_STREAM_FORMAT_BDU_FRAME:
1746           goto conversion_not_supported;
1747           break;
1748         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU:
1749           /* We just need to drop sequence-layer buffer */
1750           if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_NO_FRAME) {
1751             ret = GST_BASE_PARSE_FLOW_DROPPED;
1752           }
1753           break;
1754         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME:
1755         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME:
1756         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER:
1757           goto conversion_not_supported;
1758           break;
1759         case VC1_STREAM_FORMAT_ASF:
1760           ret = gst_vc1_parse_convert_asf_to_bdu (vc1parse, frame);
1761           break;
1762         case VC1_STREAM_FORMAT_FRAME_LAYER:
1763           goto conversion_not_supported;
1764           break;
1765         default:
1766           g_assert_not_reached ();
1767           break;
1768       }
1769       break;
1770 
1771     case VC1_STREAM_FORMAT_BDU_FRAME:
1772       switch (vc1parse->input_stream_format) {
1773         case VC1_STREAM_FORMAT_BDU:
1774           goto conversion_not_supported;
1775           break;
1776         case VC1_STREAM_FORMAT_BDU_FRAME:
1777           g_assert_not_reached ();
1778           break;
1779         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU:
1780           goto conversion_not_supported;
1781           break;
1782         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME:
1783           /* We just need to drop sequence-layer buffer */
1784           if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_NO_FRAME) {
1785             ret = GST_BASE_PARSE_FLOW_DROPPED;
1786           }
1787           break;
1788         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME:
1789         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER:
1790         case VC1_STREAM_FORMAT_ASF:
1791         case VC1_STREAM_FORMAT_FRAME_LAYER:
1792           goto conversion_not_supported;
1793           break;
1794         default:
1795           g_assert_not_reached ();
1796           break;
1797       }
1798       break;
1799 
1800     case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU:
1801       switch (vc1parse->input_stream_format) {
1802         case VC1_STREAM_FORMAT_BDU:
1803           /* We just need to send the sequence-layer first */
1804           if (!vc1parse->seq_layer_sent) {
1805             ret = gst_vc1_parse_push_sequence_layer (vc1parse);
1806             if (ret != GST_FLOW_OK) {
1807               GST_ERROR_OBJECT (vc1parse, "push sequence layer failed");
1808               break;
1809             }
1810             vc1parse->seq_layer_sent = TRUE;
1811           }
1812           break;
1813         case VC1_STREAM_FORMAT_BDU_FRAME:
1814           goto conversion_not_supported;
1815           break;
1816         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU:
1817           g_assert_not_reached ();
1818           break;
1819         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME:
1820         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME:
1821         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER:
1822           goto conversion_not_supported;
1823           break;
1824         case VC1_STREAM_FORMAT_ASF:
1825           /* We just need to send the sequence-layer first */
1826           if (!vc1parse->seq_layer_sent) {
1827             ret = gst_vc1_parse_push_sequence_layer (vc1parse);
1828             if (ret != GST_FLOW_OK) {
1829               GST_ERROR_OBJECT (vc1parse, "push sequence layer failed");
1830               break;
1831             }
1832             vc1parse->seq_layer_sent = TRUE;
1833           }
1834           /* FIXME: We may only authorize this when header-format is set to
1835            * none and we should add the entrypoint for advanced profile. */
1836           ret = gst_vc1_parse_convert_asf_to_bdu (vc1parse, frame);
1837           break;
1838         case VC1_STREAM_FORMAT_FRAME_LAYER:
1839           goto conversion_not_supported;
1840           break;
1841         default:
1842           g_assert_not_reached ();
1843           break;
1844       }
1845       break;
1846 
1847     case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME:
1848       switch (vc1parse->input_stream_format) {
1849         case VC1_STREAM_FORMAT_BDU:
1850           goto conversion_not_supported;
1851           break;
1852         case VC1_STREAM_FORMAT_BDU_FRAME:
1853           /* We just need to send the sequence-layer first */
1854           if (!vc1parse->seq_layer_sent) {
1855             ret = gst_vc1_parse_push_sequence_layer (vc1parse);
1856             if (ret != GST_FLOW_OK) {
1857               GST_ERROR_OBJECT (vc1parse, "push sequence layer failed");
1858               break;
1859             }
1860             vc1parse->seq_layer_sent = TRUE;
1861           }
1862           break;
1863         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU:
1864           goto conversion_not_supported;
1865           break;
1866         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME:
1867           g_assert_not_reached ();
1868           break;
1869         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME:
1870         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER:
1871         case VC1_STREAM_FORMAT_ASF:
1872         case VC1_STREAM_FORMAT_FRAME_LAYER:
1873           goto conversion_not_supported;
1874           break;
1875         default:
1876           g_assert_not_reached ();
1877           break;
1878       }
1879       break;
1880 
1881     case VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME:
1882       if (vc1parse->profile != GST_VC1_PROFILE_SIMPLE &&
1883           vc1parse->profile != GST_VC1_PROFILE_MAIN) {
1884         GST_ERROR_OBJECT (vc1parse,
1885             "sequence-layer-raw-frame is only for simple/main profile");
1886         goto conversion_not_supported;
1887       }
1888       switch (vc1parse->input_stream_format) {
1889         case VC1_STREAM_FORMAT_BDU:
1890         case VC1_STREAM_FORMAT_BDU_FRAME:
1891         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU:
1892         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME:
1893           goto conversion_not_supported;
1894           break;
1895         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME:
1896           g_assert_not_reached ();
1897           break;
1898         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER:
1899           goto conversion_not_supported;
1900         case VC1_STREAM_FORMAT_ASF:
1901           /* ASF contains raw frame for simple/main profile, so we just
1902            * have to send sequence-layer before frames */
1903           if (!vc1parse->seq_layer_sent) {
1904             ret = gst_vc1_parse_push_sequence_layer (vc1parse);
1905             if (ret != GST_FLOW_OK) {
1906               GST_ERROR_OBJECT (vc1parse, "push sequence layer failed");
1907               break;
1908             }
1909             vc1parse->seq_layer_sent = TRUE;
1910           }
1911           break;
1912         case VC1_STREAM_FORMAT_FRAME_LAYER:
1913           goto conversion_not_supported;
1914           break;
1915         default:
1916           g_assert_not_reached ();
1917           break;
1918       }
1919       break;
1920 
1921     case VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER:
1922       switch (vc1parse->input_stream_format) {
1923         case VC1_STREAM_FORMAT_BDU:
1924         case VC1_STREAM_FORMAT_BDU_FRAME:
1925         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU:
1926         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME:
1927         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME:
1928           goto conversion_not_supported;
1929           break;
1930         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER:
1931           g_assert_not_reached ();
1932           break;
1933         case VC1_STREAM_FORMAT_ASF:
1934           /* Make sure we push the sequence layer */
1935           if (!vc1parse->seq_layer_sent) {
1936             ret = gst_vc1_parse_push_sequence_layer (vc1parse);
1937             if (ret != GST_FLOW_OK) {
1938               GST_ERROR_OBJECT (vc1parse, "push sequence layer failed");
1939               break;
1940             }
1941             vc1parse->seq_layer_sent = TRUE;
1942           }
1943           ret = gst_vc1_parse_convert_to_frame_layer (vc1parse, frame);
1944           break;
1945         case VC1_STREAM_FORMAT_FRAME_LAYER:
1946           /* We just need to send the sequence-layer first */
1947           if (!vc1parse->seq_layer_sent) {
1948             ret = gst_vc1_parse_push_sequence_layer (vc1parse);
1949             if (ret != GST_FLOW_OK) {
1950               GST_ERROR_OBJECT (vc1parse, "push sequence layer failed");
1951               break;
1952             }
1953             vc1parse->seq_layer_sent = TRUE;
1954           }
1955           break;
1956         default:
1957           g_assert_not_reached ();
1958           break;
1959       }
1960       break;
1961 
1962     case VC1_STREAM_FORMAT_ASF:
1963       switch (vc1parse->input_stream_format) {
1964         case VC1_STREAM_FORMAT_BDU:
1965         case VC1_STREAM_FORMAT_BDU_FRAME:
1966         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU:
1967         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME:
1968         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME:
1969         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER:
1970           goto conversion_not_supported;
1971           break;
1972         case VC1_STREAM_FORMAT_ASF:
1973           g_assert_not_reached ();
1974           break;
1975         case VC1_STREAM_FORMAT_FRAME_LAYER:
1976           goto conversion_not_supported;
1977           break;
1978         default:
1979           g_assert_not_reached ();
1980           break;
1981       }
1982       break;
1983 
1984     case VC1_STREAM_FORMAT_FRAME_LAYER:
1985       switch (vc1parse->input_stream_format) {
1986         case VC1_STREAM_FORMAT_BDU:
1987         case VC1_STREAM_FORMAT_BDU_FRAME:
1988         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU:
1989         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME:
1990         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME:
1991           goto conversion_not_supported;
1992           break;
1993         case VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER:
1994           /* We just need to drop sequence-layer buffer */
1995           if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_NO_FRAME) {
1996             ret = GST_BASE_PARSE_FLOW_DROPPED;
1997           }
1998           break;
1999         case VC1_STREAM_FORMAT_ASF:
2000           ret = gst_vc1_parse_convert_to_frame_layer (vc1parse, frame);
2001           break;
2002         case VC1_STREAM_FORMAT_FRAME_LAYER:
2003         default:
2004           g_assert_not_reached ();
2005           break;
2006       }
2007       break;
2008 
2009     default:
2010       g_assert_not_reached ();
2011       break;
2012   }
2013 
2014   return ret;
2015 
2016 conversion_not_supported:
2017   GST_WARNING_OBJECT (vc1parse, "stream conversion not implemented yet");
2018   return GST_FLOW_NOT_NEGOTIATED;
2019 }
2020 
2021 /* SMPTE 421M Table 7 */
2022 static const struct
2023 {
2024   gint par_n, par_d;
2025 } aspect_ratios[] = {
2026   {
2027   0, 0}, {
2028   1, 1}, {
2029   12, 11}, {
2030   10, 11}, {
2031   16, 11}, {
2032   40, 33}, {
2033   24, 11}, {
2034   20, 11}, {
2035   32, 11}, {
2036   80, 33}, {
2037   18, 11}, {
2038   15, 11}, {
2039   64, 33}, {
2040   160, 99}, {
2041   0, 0}, {
2042   0, 0}
2043 };
2044 
2045 /* SMPTE 421M Table 8 */
2046 static const guint framerates_n[] = {
2047   0,
2048   24 * 1000,
2049   25 * 1000, 30 * 1000, 50 * 1000, 60 * 1000, 48 * 1000, 72 * 1000
2050 };
2051 
2052 /* SMPTE 421M Table 9 */
2053 static const guint framerates_d[] = {
2054   0,
2055   1000,
2056   1001
2057 };
2058 
2059 static gboolean
gst_vc1_parse_handle_seq_hdr(GstVC1Parse * vc1parse,GstBuffer * buf,guint offset,guint size)2060 gst_vc1_parse_handle_seq_hdr (GstVC1Parse * vc1parse,
2061     GstBuffer * buf, guint offset, guint size)
2062 {
2063   GstVC1ParserResult pres;
2064   GstVC1Profile profile;
2065   GstMapInfo minfo;
2066 
2067   g_assert (gst_buffer_get_size (buf) >= offset + size);
2068   gst_buffer_replace (&vc1parse->seq_hdr_buffer, NULL);
2069   memset (&vc1parse->seq_hdr, 0, sizeof (vc1parse->seq_hdr));
2070 
2071   gst_buffer_map (buf, &minfo, GST_MAP_READ);
2072   pres =
2073       gst_vc1_parse_sequence_header (minfo.data + offset,
2074       size, &vc1parse->seq_hdr);
2075   gst_buffer_unmap (buf, &minfo);
2076 
2077   if (pres != GST_VC1_PARSER_OK) {
2078     GST_ERROR_OBJECT (vc1parse, "Invalid VC1 sequence header");
2079     return FALSE;
2080   }
2081   vc1parse->seq_hdr_buffer =
2082       gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, offset, size);
2083   profile = vc1parse->seq_hdr.profile;
2084   if (vc1parse->profile != profile) {
2085     vc1parse->update_caps = TRUE;
2086     vc1parse->profile = vc1parse->seq_hdr.profile;
2087   }
2088 
2089   /* Only update fps if not from caps */
2090   if (!vc1parse->fps_from_caps && profile != GST_VC1_PROFILE_ADVANCED) {
2091     gint fps;
2092     /* This is only an estimate but better than nothing */
2093     fps = vc1parse->seq_hdr.struct_c.framerate;
2094     if (fps != 0 && (vc1parse->fps_d == 0 ||
2095             gst_util_fraction_compare (fps, 1, vc1parse->fps_n,
2096                 vc1parse->fps_d) != 0)) {
2097       vc1parse->update_caps = TRUE;
2098       vc1parse->fps_n = fps;
2099       vc1parse->fps_d = 1;
2100     }
2101   }
2102 
2103   if (profile == GST_VC1_PROFILE_ADVANCED) {
2104     GstVC1Level level;
2105     gint width, height;
2106     level = vc1parse->seq_hdr.advanced.level;
2107     if (vc1parse->level != level) {
2108       vc1parse->update_caps = TRUE;
2109       vc1parse->level = level;
2110     }
2111 
2112     width = vc1parse->seq_hdr.advanced.max_coded_width;
2113     height = vc1parse->seq_hdr.advanced.max_coded_height;
2114     if (vc1parse->width != width || vc1parse->height != height) {
2115       vc1parse->update_caps = TRUE;
2116       vc1parse->width = width;
2117       vc1parse->height = height;
2118     }
2119 
2120     /* Only update fps if not from caps */
2121     if (!vc1parse->fps_from_caps) {
2122       gint fps;
2123       /* This is only an estimate but better than nothing */
2124       fps = vc1parse->seq_hdr.advanced.framerate;
2125       if (fps != 0 && (vc1parse->fps_d == 0 ||
2126               gst_util_fraction_compare (fps, 1, vc1parse->fps_n,
2127                   vc1parse->fps_d) != 0)) {
2128         vc1parse->update_caps = TRUE;
2129         vc1parse->fps_n = fps;
2130         vc1parse->fps_d = 1;
2131       }
2132     }
2133 
2134     if (vc1parse->seq_hdr.advanced.display_ext) {
2135       /* Only update PAR if not from input caps */
2136       if (!vc1parse->par_from_caps
2137           && vc1parse->seq_hdr.advanced.aspect_ratio_flag) {
2138         gint par_n, par_d;
2139         if (vc1parse->seq_hdr.advanced.aspect_ratio == 15) {
2140           par_n = vc1parse->seq_hdr.advanced.aspect_horiz_size;
2141           par_d = vc1parse->seq_hdr.advanced.aspect_vert_size;
2142         } else {
2143           par_n = aspect_ratios[vc1parse->seq_hdr.advanced.aspect_ratio].par_n;
2144           par_d = aspect_ratios[vc1parse->seq_hdr.advanced.aspect_ratio].par_d;
2145         }
2146 
2147         if (par_n != 0 && par_d != 0 &&
2148             (vc1parse->par_d == 0
2149                 || gst_util_fraction_compare (par_n, par_d,
2150                     vc1parse->par_n, vc1parse->par_d) != 0)) {
2151           vc1parse->update_caps = TRUE;
2152           vc1parse->par_n = par_n;
2153           vc1parse->par_d = par_d;
2154         }
2155       }
2156 
2157       /* Only update fps if not from caps, better value than above */
2158       if (!vc1parse->fps_from_caps && vc1parse->seq_hdr.advanced.framerate_flag) {
2159         gint fps_n = 0, fps_d = 0;
2160         if (!vc1parse->seq_hdr.advanced.framerateind) {
2161           if (vc1parse->seq_hdr.advanced.frameratenr > 0
2162               && vc1parse->seq_hdr.advanced.frameratenr < 8
2163               && vc1parse->seq_hdr.advanced.frameratedr > 0
2164               && vc1parse->seq_hdr.advanced.frameratedr < 3) {
2165             fps_n = framerates_n[vc1parse->seq_hdr.advanced.frameratenr];
2166             fps_d = framerates_d[vc1parse->seq_hdr.advanced.frameratedr];
2167           }
2168         } else {
2169           fps_n = vc1parse->seq_hdr.advanced.framerateexp + 1;
2170           fps_d = 32;
2171         }
2172 
2173         if (fps_n != 0 && fps_d != 0 &&
2174             (vc1parse->fps_d == 0
2175                 || gst_util_fraction_compare (fps_n, fps_d,
2176                     vc1parse->fps_n, vc1parse->fps_d) != 0)) {
2177           vc1parse->update_caps = TRUE;
2178           vc1parse->fps_n = fps_n;
2179           vc1parse->fps_d = fps_d;
2180         }
2181       }
2182     }
2183   }
2184 
2185   return TRUE;
2186 }
2187 
2188 static gboolean
gst_vc1_parse_handle_seq_layer(GstVC1Parse * vc1parse,GstBuffer * buf,guint offset,guint size)2189 gst_vc1_parse_handle_seq_layer (GstVC1Parse * vc1parse,
2190     GstBuffer * buf, guint offset, guint size)
2191 {
2192   GstVC1ParserResult pres;
2193   GstVC1Profile profile;
2194   GstVC1Level level;
2195   gint width, height;
2196   GstMapInfo minfo;
2197 
2198   g_assert (gst_buffer_get_size (buf) >= offset + size);
2199 
2200   gst_buffer_replace (&vc1parse->seq_layer_buffer, NULL);
2201   memset (&vc1parse->seq_layer, 0, sizeof (vc1parse->seq_layer));
2202 
2203   gst_buffer_map (buf, &minfo, GST_MAP_READ);
2204   pres =
2205       gst_vc1_parse_sequence_layer (minfo.data + offset,
2206       size, &vc1parse->seq_layer);
2207   gst_buffer_unmap (buf, &minfo);
2208 
2209   if (pres != GST_VC1_PARSER_OK) {
2210     GST_ERROR_OBJECT (vc1parse, "Invalid VC1 sequence layer");
2211     return FALSE;
2212   }
2213   vc1parse->seq_layer_buffer =
2214       gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, offset, size);
2215   profile = vc1parse->seq_layer.struct_c.profile;
2216   if (vc1parse->profile != profile) {
2217     vc1parse->update_caps = TRUE;
2218     vc1parse->profile = vc1parse->seq_layer.struct_c.profile;
2219   }
2220 
2221   width = vc1parse->seq_layer.struct_a.vert_size;
2222   height = vc1parse->seq_layer.struct_a.horiz_size;
2223   if (width > 0 && height > 0
2224       && (vc1parse->width != width || vc1parse->height != height)) {
2225     vc1parse->update_caps = TRUE;
2226     vc1parse->width = width;
2227     vc1parse->height = height;
2228   }
2229 
2230   level = vc1parse->seq_layer.struct_b.level;
2231   if (vc1parse->level != level) {
2232     vc1parse->update_caps = TRUE;
2233     vc1parse->level = level;
2234   }
2235 
2236   if (!vc1parse->fps_from_caps && profile != GST_VC1_PROFILE_ADVANCED) {
2237     gint fps;
2238     fps = vc1parse->seq_layer.struct_c.framerate;
2239     if (fps == 0 || fps == -1)
2240       fps = vc1parse->seq_layer.struct_b.framerate;
2241     if (fps != 0 && fps != -1 && (vc1parse->fps_d == 0 ||
2242             gst_util_fraction_compare (fps, 1, vc1parse->fps_n,
2243                 vc1parse->fps_d) != 0)) {
2244       vc1parse->update_caps = TRUE;
2245       vc1parse->fps_n = fps;
2246       vc1parse->fps_d = 1;
2247     }
2248   }
2249 
2250   /* And now update the duration */
2251   if (vc1parse->seq_layer.numframes != 0 && vc1parse->seq_layer.numframes != -1)
2252     gst_base_parse_set_duration (GST_BASE_PARSE (vc1parse),
2253         GST_FORMAT_DEFAULT, vc1parse->seq_layer.numframes, 50);
2254   return TRUE;
2255 }
2256 
2257 static gboolean
gst_vc1_parse_handle_entrypoint(GstVC1Parse * vc1parse,GstBuffer * buf,guint offset,guint size)2258 gst_vc1_parse_handle_entrypoint (GstVC1Parse * vc1parse,
2259     GstBuffer * buf, guint offset, guint size)
2260 {
2261   g_assert (gst_buffer_get_size (buf) >= offset + size);
2262 
2263   gst_buffer_replace (&vc1parse->entrypoint_buffer, NULL);
2264   vc1parse->entrypoint_buffer =
2265       gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, offset, size);
2266 
2267   return TRUE;
2268 }
2269 
2270 static void
gst_vc1_parse_update_stream_format_properties(GstVC1Parse * vc1parse)2271 gst_vc1_parse_update_stream_format_properties (GstVC1Parse * vc1parse)
2272 {
2273   if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU
2274       || vc1parse->input_stream_format == VC1_STREAM_FORMAT_BDU_FRAME) {
2275     /* Need at least the 4 bytes start code */
2276     gst_base_parse_set_min_frame_size (GST_BASE_PARSE (vc1parse), 4);
2277     gst_base_parse_set_syncable (GST_BASE_PARSE (vc1parse), TRUE);
2278   } else
2279       if (vc1parse->input_stream_format ==
2280       VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU
2281       || vc1parse->input_stream_format ==
2282       VC1_STREAM_FORMAT_SEQUENCE_LAYER_BDU_FRAME) {
2283     /* Need at least the 36 bytes sequence layer */
2284     gst_base_parse_set_min_frame_size (GST_BASE_PARSE (vc1parse), 36);
2285     gst_base_parse_set_syncable (GST_BASE_PARSE (vc1parse), TRUE);
2286   } else
2287       if (vc1parse->input_stream_format ==
2288       VC1_STREAM_FORMAT_SEQUENCE_LAYER_RAW_FRAME
2289       || vc1parse->input_stream_format ==
2290       VC1_STREAM_FORMAT_SEQUENCE_LAYER_FRAME_LAYER) {
2291     /* Need at least the 36 bytes sequence layer */
2292     gst_base_parse_set_min_frame_size (GST_BASE_PARSE (vc1parse), 36);
2293     gst_base_parse_set_syncable (GST_BASE_PARSE (vc1parse), FALSE);
2294   } else if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_ASF) {
2295     vc1parse->input_stream_format = VC1_STREAM_FORMAT_ASF;
2296     /* Need something, assume this is already packetized */
2297     gst_base_parse_set_min_frame_size (GST_BASE_PARSE (vc1parse), 1);
2298     gst_base_parse_set_syncable (GST_BASE_PARSE (vc1parse), FALSE);
2299   } else if (vc1parse->input_stream_format == VC1_STREAM_FORMAT_FRAME_LAYER) {
2300     /* Need at least the frame layer header */
2301     gst_base_parse_set_min_frame_size (GST_BASE_PARSE (vc1parse), 8);
2302     gst_base_parse_set_syncable (GST_BASE_PARSE (vc1parse), FALSE);
2303   } else {
2304     g_assert_not_reached ();
2305   }
2306 }
2307 
2308 static gboolean
gst_vc1_parse_set_caps(GstBaseParse * parse,GstCaps * caps)2309 gst_vc1_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
2310 {
2311   GstVC1Parse *vc1parse = GST_VC1_PARSE (parse);
2312   GstStructure *s;
2313   const GValue *value;
2314   GstBuffer *codec_data = NULL;
2315   const gchar *stream_format = NULL;
2316   const gchar *header_format = NULL;
2317   const gchar *profile = NULL;
2318   const gchar *format;
2319 
2320   GST_DEBUG_OBJECT (parse, "caps %" GST_PTR_FORMAT, caps);
2321   /* Parse the caps to get as much information as possible */
2322   s = gst_caps_get_structure (caps, 0);
2323 
2324   vc1parse->width = 0;
2325   gst_structure_get_int (s, "width", &vc1parse->width);
2326   vc1parse->height = 0;
2327   gst_structure_get_int (s, "height", &vc1parse->height);
2328 
2329   vc1parse->fps_n = vc1parse->fps_d = 0;
2330   vc1parse->fps_from_caps = FALSE;
2331   gst_structure_get_fraction (s, "framerate", &vc1parse->fps_n,
2332       &vc1parse->fps_d);
2333   if (vc1parse->fps_d != 0)
2334     vc1parse->fps_from_caps = TRUE;
2335 
2336   gst_structure_get_fraction (s, "pixel-aspect-ratio",
2337       &vc1parse->par_n, &vc1parse->par_d);
2338   if (vc1parse->par_n != 0 && vc1parse->par_d != 0)
2339     vc1parse->par_from_caps = TRUE;
2340 
2341   vc1parse->format = 0;
2342   format = gst_structure_get_string (s, "format");
2343   if (format && strcmp (format, "WVC1") == 0)
2344     vc1parse->format = GST_VC1_PARSE_FORMAT_WVC1;
2345   else
2346     vc1parse->format = GST_VC1_PARSE_FORMAT_WMV3;
2347 
2348   vc1parse->profile = -1;
2349   profile = gst_structure_get_string (s, "profile");
2350   if (profile && strcmp (profile, "simple"))
2351     vc1parse->profile = GST_VC1_PROFILE_SIMPLE;
2352   else if (profile && strcmp (profile, "main"))
2353     vc1parse->profile = GST_VC1_PROFILE_MAIN;
2354   else if (profile && strcmp (profile, "advanced"))
2355     vc1parse->profile = GST_VC1_PROFILE_ADVANCED;
2356   else if (vc1parse->format == GST_VC1_PARSE_FORMAT_WVC1)
2357     vc1parse->profile = GST_VC1_PROFILE_ADVANCED;
2358   else if (vc1parse->format == GST_VC1_PARSE_FORMAT_WMV3)
2359     vc1parse->profile = GST_VC1_PROFILE_MAIN;   /* or SIMPLE */
2360 
2361   vc1parse->level = -1;
2362   vc1parse->detecting_stream_format = FALSE;
2363   header_format = gst_structure_get_string (s, "header-format");
2364   stream_format = gst_structure_get_string (s, "stream-format");
2365 
2366   /* Now parse the codec_data */
2367   gst_buffer_replace (&vc1parse->seq_layer_buffer, NULL);
2368   gst_buffer_replace (&vc1parse->seq_hdr_buffer, NULL);
2369   gst_buffer_replace (&vc1parse->entrypoint_buffer, NULL);
2370   memset (&vc1parse->seq_layer, 0, sizeof (vc1parse->seq_layer));
2371   memset (&vc1parse->seq_hdr, 0, sizeof (vc1parse->seq_hdr));
2372   value = gst_structure_get_value (s, "codec_data");
2373 
2374   if (value != NULL) {
2375     gsize codec_data_size;
2376     GstMapInfo minfo;
2377 
2378     codec_data = gst_value_get_buffer (value);
2379     gst_buffer_map (codec_data, &minfo, GST_MAP_READ);
2380     codec_data_size = gst_buffer_get_size (codec_data);
2381     if ((codec_data_size == 4 || codec_data_size == 5)) {
2382       /* ASF, VC1/WMV3 simple/main profile
2383        * This is the sequence header without start codes
2384        */
2385       if (!gst_vc1_parse_handle_seq_hdr (vc1parse, codec_data,
2386               0, codec_data_size)) {
2387         gst_buffer_unmap (codec_data, &minfo);
2388         return FALSE;
2389       }
2390       if (header_format && strcmp (header_format, "asf") != 0)
2391         GST_WARNING_OBJECT (vc1parse,
2392             "Upstream claimed '%s' header format but 'asf' detected",
2393             header_format);
2394       vc1parse->input_header_format = VC1_HEADER_FORMAT_ASF;
2395     } else if (codec_data_size == 36 && minfo.data[3] == 0xc5) {
2396       /* Sequence Layer, SMPTE S421M-2006 Annex L.3 */
2397       if (!gst_vc1_parse_handle_seq_layer (vc1parse, codec_data, 0,
2398               codec_data_size)) {
2399         GST_ERROR_OBJECT (vc1parse, "Invalid VC1 sequence layer");
2400         gst_buffer_unmap (codec_data, &minfo);
2401         return FALSE;
2402       }
2403 
2404       if (header_format && strcmp (header_format, "sequence-layer") != 0)
2405         GST_WARNING_OBJECT (vc1parse,
2406             "Upstream claimed '%s' header format but 'sequence-layer' detected",
2407             header_format);
2408       vc1parse->input_header_format = VC1_HEADER_FORMAT_SEQUENCE_LAYER;
2409     } else {
2410       guint32 start_code;
2411       /* ASF, VC1 advanced profile
2412        * This should be the
2413        * 1) ASF binding byte
2414        * 2) Sequence Header with startcode
2415        * 3) EntryPoint Header with startcode
2416        */
2417       if (codec_data_size < 1 + 4 + 4 + 4 + 2) {
2418         GST_ERROR_OBJECT (vc1parse,
2419             "Too small for VC1 advanced profile ASF header");
2420         gst_buffer_unmap (codec_data, &minfo);
2421         return FALSE;
2422       }
2423 
2424       /* Some sanity checking */
2425       if ((minfo.data[0] & 0x01) != 0x01) {
2426         GST_ERROR_OBJECT (vc1parse,
2427             "Invalid binding byte for VC1 advanced profile ASF header");
2428         gst_buffer_unmap (codec_data, &minfo);
2429         return FALSE;
2430       }
2431 
2432       start_code = GST_READ_UINT32_BE (minfo.data + 1);
2433       if (start_code != 0x000010f) {
2434         GST_ERROR_OBJECT (vc1parse,
2435             "VC1 advanced profile ASF header does not start with SequenceHeader startcode");
2436         gst_buffer_unmap (codec_data, &minfo);
2437         return FALSE;
2438       }
2439 
2440       if (!gst_vc1_parse_handle_bdus (vc1parse, codec_data, 1,
2441               codec_data_size - 1)) {
2442         gst_buffer_unmap (codec_data, &minfo);
2443         return FALSE;
2444       }
2445 
2446       if (!vc1parse->seq_hdr_buffer || !vc1parse->entrypoint_buffer) {
2447         GST_ERROR_OBJECT (vc1parse,
2448             "Need sequence header and entrypoint header in the codec_data");
2449         gst_buffer_unmap (codec_data, &minfo);
2450         return FALSE;
2451       }
2452 
2453       if (header_format && strcmp (header_format, "asf") != 0)
2454         GST_WARNING_OBJECT (vc1parse,
2455             "Upstream claimed '%s' header format but 'asf' detected",
2456             header_format);
2457 
2458       vc1parse->input_header_format = VC1_HEADER_FORMAT_ASF;
2459     }
2460     gst_buffer_unmap (codec_data, &minfo);
2461   } else {
2462     vc1parse->input_header_format = VC1_HEADER_FORMAT_NONE;
2463     if (header_format && strcmp (header_format, "none") != 0)
2464       GST_WARNING_OBJECT (vc1parse,
2465           "Upstream claimed '%s' header format but 'none' detected",
2466           header_format);
2467   }
2468 
2469   /* If no stream-format was set we try to detect it */
2470   if (!stream_format) {
2471     vc1parse->detecting_stream_format = TRUE;
2472   } else {
2473     vc1parse->input_stream_format = stream_format_from_string (stream_format);
2474     gst_vc1_parse_update_stream_format_properties (vc1parse);
2475   }
2476 
2477   vc1parse->renegotiate = TRUE;
2478   vc1parse->update_caps = TRUE;
2479   return TRUE;
2480 }
2481