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