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