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