gstflvparse.c 39.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* GStreamer
 * Copyright (C) <2007> Julien Moutte <julien@moutte.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include "gstflvparse.h"

22
23
#include <gst/base/gstbytereader.h>

24
25
26
27
28
29
#include <string.h>

GST_DEBUG_CATEGORY_EXTERN (flvdemux_debug);
#define GST_CAT_DEFAULT flvdemux_debug

static gchar *
30
FLV_GET_STRING (GstByteReader * reader)
31
{
32
  guint16 string_size = 0;
33
  gchar *string = NULL;
34
  const guint8 *str = NULL;
35

36
  g_return_val_if_fail (reader != NULL, NULL);
37

38
39
40
41
  if (G_UNLIKELY (!gst_byte_reader_get_uint16_be (reader, &string_size)))
    return NULL;

  if (G_UNLIKELY (string_size > gst_byte_reader_get_remaining (reader)))
42
    return NULL;
43
44
45
46
47
48

  string = g_try_malloc0 (string_size + 1);
  if (G_UNLIKELY (!string)) {
    return NULL;
  }

49
50
51
52
53
54
  if (G_UNLIKELY (!gst_byte_reader_get_data (reader, string_size, &str))) {
    g_free (string);
    return NULL;
  }

  memcpy (string, str, string_size);
55
56
57
58
  if (!g_utf8_validate (string, string_size, NULL)) {
    g_free (string);
    return NULL;
  }
59
60
61
62
63
64
65
66
67

  return string;
}

static const GstQueryType *
gst_flv_demux_query_types (GstPad * pad)
{
  static const GstQueryType query_types[] = {
    GST_QUERY_DURATION,
68
69
    GST_QUERY_POSITION,
    GST_QUERY_SEEKING,
70
71
72
73
74
75
    0
  };

  return query_types;
}

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
static void
parse_flv_date_string (GDate * date, const gchar * s)
{
  g_date_set_parse (date, s);
  if (g_date_valid (date))
    return;

  /* "Fri Oct 15 15:13:16 2004" needs to be parsed */
  {
    static const gchar *months[] = {
      "Jan", "Feb", "Mar", "Apr",
      "May", "Jun", "Jul", "Aug",
      "Sep", "Oct", "Nov", "Dec"
    };
    gchar **tokens = g_strsplit (s, " ", -1);
    guint64 d;
    gchar *endptr;
    gint i;

    if (g_strv_length (tokens) != 5)
      goto out;

    if (strlen (tokens[1]) != 3)
      goto out;
    for (i = 0; i < 12; i++) {
      if (!strcmp (tokens[1], months[i])) {
        break;
      }
    }
    if (i == 12)
      goto out;
    g_date_set_month (date, i + 1);

    d = g_ascii_strtoull (tokens[2], &endptr, 10);
    if (d == 0 && *endptr != '\0')
      goto out;

    g_date_set_day (date, d);

    d = g_ascii_strtoull (tokens[4], &endptr, 10);
    if (d == 0 && *endptr != '\0')
      goto out;

    g_date_set_year (date, d);

  out:
    if (tokens)
      g_strfreev (tokens);
  }
}

127
128
129
static gboolean
gst_flv_parse_metadata_item (GstFLVDemux * demux, GstByteReader * reader,
    gboolean * end_marker)
130
131
132
133
{
  gchar *tag_name = NULL;
  guint8 tag_type = 0;

134
135
136
  /* Initialize the end_marker flag to FALSE */
  *end_marker = FALSE;

137
  /* Name of the tag */
138
  tag_name = FLV_GET_STRING (reader);
139
140
  if (G_UNLIKELY (!tag_name)) {
    GST_WARNING_OBJECT (demux, "failed reading tag name");
141
    return FALSE;
142
  }
143
144

  /* What kind of object is that */
145
146
  if (!gst_byte_reader_get_uint8 (reader, &tag_type))
    goto error;
147
148
149
150
151
152

  GST_DEBUG_OBJECT (demux, "tag name %s, tag type %d", tag_name, tag_type);

  switch (tag_type) {
    case 0:                    // Double
    {                           /* Use a union to read the uint64 and then as a double */
153
      gdouble d = 0;
154

155
156
      if (!gst_byte_reader_get_float64_be (reader, &d))
        goto error;
157

158
      GST_DEBUG_OBJECT (demux, "%s => (double) %f", tag_name, d);
159
160

      if (!strcmp (tag_name, "duration")) {
161
        demux->duration = d * GST_SECOND;
162
163
164

        gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
            GST_TAG_DURATION, demux->duration, NULL);
165
166
167
168
169
170
      } else if (!strcmp (tag_name, "AspectRatioX")) {
        demux->par_x = d;
        demux->got_par = TRUE;
      } else if (!strcmp (tag_name, "AspectRatioY")) {
        demux->par_y = d;
        demux->got_par = TRUE;
171
      } else {
172
        GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
173
174
175
176
177
178
      }

      break;
    }
    case 1:                    // Boolean
    {
179
      guint8 b = 0;
180

181
182
      if (!gst_byte_reader_get_uint8 (reader, &b))
        goto error;
183

184
      GST_DEBUG_OBJECT (demux, "%s => (boolean) %d", tag_name, b);
185

186
      GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
187
188
189
190
191

      break;
    }
    case 2:                    // String
    {
192
      gchar *s = NULL;
193

194
195
196
      s = FLV_GET_STRING (reader);
      if (s == NULL)
        goto error;
197

198
      GST_DEBUG_OBJECT (demux, "%s => (string) %s", tag_name, s);
199

200
201
      if (!strcmp (tag_name, "creationdate")) {
        GDate *date = g_date_new ();
202

203
204
205
        parse_flv_date_string (date, s);
        if (!g_date_valid (date)) {
          GST_DEBUG_OBJECT (demux, "Failed to parse string as date");
206
        } else {
207
208
          gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
              GST_TAG_DATE, date, NULL);
209
        }
210
211
212
213
        g_date_free (date);
      } else if (!strcmp (tag_name, "creator")) {
        gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
            GST_TAG_ARTIST, s, NULL);
214
215
216
      } else if (!strcmp (tag_name, "title")) {
        gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
            GST_TAG_TITLE, s, NULL);
217
218
219
220
221
      } else if (!strcmp (tag_name, "metadatacreator")) {
        gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
            GST_TAG_ENCODER, s, NULL);
      } else {
        GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
222
223
      }

224
      g_free (s);
225
226
227

      break;
    }
228
229
230
231
    case 3:                    // Object
    {
      gboolean end_of_object_marker = FALSE;

232
233
234
      while (!end_of_object_marker) {
        gboolean ok =
            gst_flv_parse_metadata_item (demux, reader, &end_of_object_marker);
235

236
        if (G_UNLIKELY (!ok)) {
237
          GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
238
          goto error;
239
240
241
242
243
        }
      }

      break;
    }
244
245
    case 8:                    // ECMA array
    {
246
      guint32 nb_elems = 0;
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
      gboolean end_of_object_marker = FALSE;

      if (!gst_byte_reader_get_uint32_be (reader, &nb_elems))
        goto error;

      GST_DEBUG_OBJECT (demux, "there are approx. %d elements in the array",
          nb_elems);

      while (!end_of_object_marker) {
        gboolean ok =
            gst_flv_parse_metadata_item (demux, reader, &end_of_object_marker);

        if (G_UNLIKELY (!ok)) {
          GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
          goto error;
        }
      }

      break;
    }
267
268
269
270
271
272
273
274
275
276
277
278
279
280
    case 9:                    // End marker
    {
      GST_DEBUG_OBJECT (demux, "end marker ?");
      if (tag_name[0] == '\0') {

        GST_DEBUG_OBJECT (demux, "end marker detected");

        *end_marker = TRUE;
      }

      break;
    }
    case 10:                   // Array
    {
281
      guint32 nb_elems = 0;
282

283
284
      if (!gst_byte_reader_get_uint32_be (reader, &nb_elems))
        goto error;
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300

      GST_DEBUG_OBJECT (demux, "array has %d elements", nb_elems);

      if (!strcmp (tag_name, "times")) {
        if (demux->times) {
          g_array_free (demux->times, TRUE);
        }
        demux->times = g_array_new (FALSE, TRUE, sizeof (gdouble));
      } else if (!strcmp (tag_name, "filepositions")) {
        if (demux->filepositions) {
          g_array_free (demux->filepositions, TRUE);
        }
        demux->filepositions = g_array_new (FALSE, TRUE, sizeof (gdouble));
      }

      while (nb_elems--) {
301
        guint8 elem_type = 0;
302

303
304
        if (!gst_byte_reader_get_uint8 (reader, &elem_type))
          goto error;
305
306
307
308

        switch (elem_type) {
          case 0:
          {
309
            gdouble d;
310

311
312
            if (!gst_byte_reader_get_float64_be (reader, &d))
              goto error;
313

314
            GST_DEBUG_OBJECT (demux, "element is a double %f", d);
315
316

            if (!strcmp (tag_name, "times") && demux->times) {
317
              g_array_append_val (demux->times, d);
318
319
            } else if (!strcmp (tag_name, "filepositions") &&
                demux->filepositions) {
320
              g_array_append_val (demux->filepositions, d);
321
322
323
324
325
326
327
328
329
330
331
332
333
            }
            break;
          }
          default:
            GST_WARNING_OBJECT (demux, "unsupported array element type %d",
                elem_type);
        }
      }

      break;
    }
    case 11:                   // Date
    {
334
335
      gdouble d = 0;
      gint16 i = 0;
336

337
338
      if (!gst_byte_reader_get_float64_be (reader, &d))
        goto error;
339

340
      if (!gst_byte_reader_get_int16_be (reader, &i))
341
        goto error;
342

343
344
345
346
      GST_DEBUG_OBJECT (demux,
          "%s => (date as a double) %f, timezone offset %d", tag_name, d, i);

      GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
347
348
349

      break;
    }
350
351
352
353
354
355
    default:
      GST_WARNING_OBJECT (demux, "unsupported tag type %d", tag_type);
  }

  g_free (tag_name);

356
357
358
359
360
361
  return TRUE;

error:
  g_free (tag_name);

  return FALSE;
362
363
364
}

GstFlowReturn
365
gst_flv_parse_tag_script (GstFLVDemux * demux, GstBuffer * buffer)
366
367
{
  GstFlowReturn ret = GST_FLOW_OK;
368
  GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
369
  guint8 type = 0;
370

371
372
373
  g_return_val_if_fail (GST_BUFFER_SIZE (buffer) >= 7, GST_FLOW_ERROR);

  gst_byte_reader_skip (&reader, 7);
374
375
376

  GST_LOG_OBJECT (demux, "parsing a script tag");

377
378
379
380
381
  if (!gst_byte_reader_get_uint8 (&reader, &type))
    return GST_FLOW_OK;

  /* Must be string */
  if (type == 2) {
382
    gchar *function_name;
383
    guint i;
384

385
    function_name = FLV_GET_STRING (&reader);
386
387

    GST_LOG_OBJECT (demux, "function name is %s", GST_STR_NULL (function_name));
388

389
    if (function_name != NULL && strcmp (function_name, "onMetaData") == 0) {
390
      guint32 nb_elems = 0;
391
      gboolean end_marker = FALSE;
392
393
394

      GST_DEBUG_OBJECT (demux, "we have a metadata script object");

395
396
397
398
399
      /* Next type must be a ECMA array */
      if (!gst_byte_reader_get_uint8 (&reader, &type) || type != 8) {
        g_free (function_name);
        return GST_FLOW_OK;
      }
400

401
402
403
404
      if (!gst_byte_reader_get_uint32_be (&reader, &nb_elems)) {
        g_free (function_name);
        return GST_FLOW_OK;
      }
405

406
407
      GST_DEBUG_OBJECT (demux, "there are approx. %d elements in the array",
          nb_elems);
408

409
      while (nb_elems-- && !end_marker) {
410
        gboolean ok = gst_flv_parse_metadata_item (demux, &reader, &end_marker);
411

412
        if (G_UNLIKELY (!ok)) {
413
414
415
          GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
          break;
        }
416
417
418
419
420
421
      }

      demux->push_tags = TRUE;
    }

    g_free (function_name);
422

423
424
    if (demux->index && demux->times && demux->filepositions
        && !demux->random_access) {
425
426
      guint num;

427
      /* If an index was found and we're in push mode, insert associations */
428
429
      num = MIN (demux->times->len, demux->filepositions->len);
      for (i = 0; i < num; i++) {
430
        GstIndexAssociation associations[2];
431
432
433
434
435
436
        guint64 time, fileposition;

        time = g_array_index (demux->times, gdouble, i) * GST_SECOND;
        fileposition = g_array_index (demux->filepositions, gdouble, i);
        GST_LOG_OBJECT (demux, "adding association %" GST_TIME_FORMAT "-> %"
            G_GUINT64_FORMAT, GST_TIME_ARGS (time), fileposition);
437
438
439
440
441
442
        associations[0].format = GST_FORMAT_TIME;
        associations[0].value = time;
        associations[1].format = GST_FORMAT_BYTES;
        associations[1].value = fileposition;

        gst_index_add_associationv (demux->index, demux->index_id,
443
            GST_ASSOCIATION_FLAG_KEY_UNIT, 2, associations);
444
      }
445
      demux->indexed = TRUE;
446
    }
447
448
449
450
451
  }

  return ret;
}

452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
static gboolean
gst_flv_parse_audio_negotiate (GstFLVDemux * demux, guint32 codec_tag,
    guint32 rate, guint32 channels, guint32 width)
{
  GstCaps *caps = NULL;
  gchar *codec_name = NULL;
  gboolean ret = FALSE;

  switch (codec_tag) {
    case 1:
      caps = gst_caps_new_simple ("audio/x-adpcm", "layout", G_TYPE_STRING,
          "swf", NULL);
      codec_name = "Shockwave ADPCM";
      break;
    case 2:
467
    case 14:
468
      caps = gst_caps_new_simple ("audio/mpeg",
469
470
          "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 3,
          "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
471
472
473
474
      codec_name = "MPEG 1 Audio, Layer 3 (MP3)";
      break;
    case 0:
    case 3:
475
476
477
      /* Assuming little endian for 0 (aka endianness of the
       * system on which the file was created) as most people
       * are probably using little endian machines */
478
      caps = gst_caps_new_simple ("audio/x-raw-int",
479
480
          "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
          "signed", G_TYPE_BOOLEAN, (width == 8) ? FALSE : TRUE,
481
482
483
484
485
486
487
488
489
490
491
          "width", G_TYPE_INT, width, "depth", G_TYPE_INT, width, NULL);
      codec_name = "Raw Audio";
      break;
    case 4:
    case 5:
    case 6:
      caps = gst_caps_new_simple ("audio/x-nellymoser", NULL);
      codec_name = "Nellymoser ASAO";
      break;
    case 10:
      caps = gst_caps_new_simple ("audio/mpeg",
492
          "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE, NULL);
493
494
      codec_name = "AAC";
      break;
495
496
497
498
499
500
501
502
    case 7:
      caps = gst_caps_new_simple ("audio/x-alaw", NULL);
      codec_name = "A-Law";
      break;
    case 8:
      caps = gst_caps_new_simple ("audio/x-mulaw", NULL);
      codec_name = "Mu-Law";
      break;
503
504
505
506
    case 11:
      caps = gst_caps_new_simple ("audio/x-speex", NULL);
      codec_name = "Speex";
      break;
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
    default:
      GST_WARNING_OBJECT (demux, "unsupported audio codec tag %u", codec_tag);
  }

  if (G_UNLIKELY (!caps)) {
    GST_WARNING_OBJECT (demux, "failed creating caps for audio pad");
    goto beach;
  }

  gst_caps_set_simple (caps,
      "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, channels, NULL);

  if (demux->audio_codec_data) {
    gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
        demux->audio_codec_data, NULL);
  }

  ret = gst_pad_set_caps (demux->audio_pad, caps);

  if (G_LIKELY (ret)) {
    /* Store the caps we have set */
    demux->audio_codec_tag = codec_tag;
    demux->rate = rate;
    demux->channels = channels;
    demux->width = width;

    if (codec_name) {
      if (demux->taglist == NULL)
        demux->taglist = gst_tag_list_new ();
      gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
          GST_TAG_AUDIO_CODEC, codec_name, NULL);
    }

    GST_DEBUG_OBJECT (demux->audio_pad, "successfully negotiated caps %"
        GST_PTR_FORMAT, caps);
  } else {
    GST_WARNING_OBJECT (demux->audio_pad, "failed negotiating caps %"
        GST_PTR_FORMAT, caps);
  }

  gst_caps_unref (caps);

beach:
  return ret;
}

553
GstFlowReturn
554
gst_flv_parse_tag_audio (GstFLVDemux * demux, GstBuffer * buffer)
555
556
{
  GstFlowReturn ret = GST_FLOW_OK;
557
  guint32 pts = 0, codec_tag = 0, rate = 5512, width = 8, channels = 1;
558
  guint32 codec_data = 0, pts_ext = 0;
559
  guint8 flags = 0;
560
561
  guint8 *data = GST_BUFFER_DATA (buffer);
  GstBuffer *outbuf;
562
563
564

  GST_LOG_OBJECT (demux, "parsing an audio tag");

565
566
567
568
569
570
  if (demux->no_more_pads && !demux->audio_pad) {
    GST_WARNING_OBJECT (demux,
        "Signaled no-more-pads already but had no audio pad -- ignoring");
    goto beach;
  }

571
572
  g_return_val_if_fail (GST_BUFFER_SIZE (buffer) == demux->tag_size,
      GST_FLOW_ERROR);
573

574
575
576
  GST_LOG_OBJECT (demux, "pts bytes %02X %02X %02X %02X", data[0], data[1],
      data[2], data[3]);

577
  /* Grab information about audio tag */
578
  pts = GST_READ_UINT24_BE (data);
579
580
581
582
  /* read the pts extension to 32 bits integer */
  pts_ext = GST_READ_UINT8 (data + 3);
  /* Combine them */
  pts |= pts_ext << 24;
583

584
585
586
587
  /* Error out on tags with too small headers */
  if (GST_BUFFER_SIZE (buffer) < 11) {
    GST_ERROR_OBJECT (demux, "Too small tag size (%d)",
        GST_BUFFER_SIZE (buffer));
588
589
590
    return GST_FLOW_ERROR;
  }

591
592
593
594
  /* Silently skip buffers with no data */
  if (GST_BUFFER_SIZE (buffer) == 11)
    return GST_FLOW_OK;

595
  /* Skip the stream id and go directly to the flags */
596
597
598
599
600
601
602
603
604
605
606
  flags = GST_READ_UINT8 (data + 7);

  /* Channels */
  if (flags & 0x01) {
    channels = 2;
  }
  /* Width */
  if (flags & 0x02) {
    width = 16;
  }
  /* Sampling rate */
607
  if ((flags & 0x0C) == 0x0C) {
608
    rate = 44100;
609
  } else if ((flags & 0x0C) == 0x08) {
610
    rate = 22050;
611
  } else if ((flags & 0x0C) == 0x04) {
612
613
614
    rate = 11025;
  }
  /* Codec tag */
615
  codec_tag = flags >> 4;
616
617
618
619
620
  if (codec_tag == 10) {        /* AAC has an extra byte for packet type */
    codec_data = 2;
  } else {
    codec_data = 1;
  }
621

622
623
624
625
626
627
  /* codec tags with special rates */
  if (codec_tag == 5 || codec_tag == 14)
    rate = 8000;
  else if (codec_tag == 4)
    rate = 16000;

628
  GST_LOG_OBJECT (demux, "audio tag with %d channels, %dHz sampling rate, "
629
630
      "%d bits width, codec tag %u (flags %02X)", channels, rate, width,
      codec_tag, flags);
631
632
633
634

  /* If we don't have our audio pad created, then create it. */
  if (G_UNLIKELY (!demux->audio_pad)) {

635
636
637
    demux->audio_pad =
        gst_pad_new_from_template (gst_element_class_get_pad_template
        (GST_ELEMENT_GET_CLASS (demux), "audio"), "audio");
638
639
640
641
642
643
    if (G_UNLIKELY (!demux->audio_pad)) {
      GST_WARNING_OBJECT (demux, "failed creating audio pad");
      ret = GST_FLOW_ERROR;
      goto beach;
    }

644
645
646
    /* Negotiate caps */
    if (!gst_flv_parse_audio_negotiate (demux, codec_tag, rate, channels,
            width)) {
647
648
      gst_object_unref (demux->audio_pad);
      demux->audio_pad = NULL;
649
      ret = GST_FLOW_ERROR;
650
651
652
      goto beach;
    }

653
    GST_DEBUG_OBJECT (demux, "created audio pad with caps %" GST_PTR_FORMAT,
654
        GST_PAD_CAPS (demux->audio_pad));
655
656
657
658
659
660

    /* Set functions on the pad */
    gst_pad_set_query_type_function (demux->audio_pad,
        GST_DEBUG_FUNCPTR (gst_flv_demux_query_types));
    gst_pad_set_query_function (demux->audio_pad,
        GST_DEBUG_FUNCPTR (gst_flv_demux_query));
661
662
    gst_pad_set_event_function (demux->audio_pad,
        GST_DEBUG_FUNCPTR (gst_flv_demux_src_event));
663

664
665
666
667
668
    gst_pad_use_fixed_caps (demux->audio_pad);

    /* Make it active */
    gst_pad_set_active (demux->audio_pad, TRUE);

669
    /* We need to set caps before adding */
670
671
672
    gst_element_add_pad (GST_ELEMENT (demux),
        gst_object_ref (demux->audio_pad));

673
674
675
676
    /* We only emit no more pads when we have audio and video. Indeed we can
     * not trust the FLV header to tell us if there will be only audio or 
     * only video and we would just break discovery of some files */
    if (demux->audio_pad && demux->video_pad) {
677
678
      GST_DEBUG_OBJECT (demux, "emitting no more pads");
      gst_element_no_more_pads (GST_ELEMENT (demux));
679
      demux->no_more_pads = TRUE;
680
    }
681
682
683
684
685
686
687
  }

  /* Check if caps have changed */
  if (G_UNLIKELY (rate != demux->rate || channels != demux->channels ||
          codec_tag != demux->audio_codec_tag || width != demux->width)) {
    GST_DEBUG_OBJECT (demux, "audio settings have changed, changing caps");

688
    /* Negotiate caps */
689
690
691
692
693
    if (!gst_flv_parse_audio_negotiate (demux, codec_tag, rate, channels,
            width)) {
      ret = GST_FLOW_ERROR;
      goto beach;
    }
694
695
696
  }

  /* Push taglist if present */
697
  if ((demux->has_audio && !demux->audio_pad) &&
698
699
700
701
702
703
704
705
706
707
      (demux->has_video && !demux->video_pad)) {
    GST_DEBUG_OBJECT (demux, "we are still waiting for a stream to come up "
        "before we can push tags");
  } else {
    if (demux->taglist && demux->push_tags) {
      GST_DEBUG_OBJECT (demux, "pushing tags out");
      gst_element_found_tags (GST_ELEMENT (demux), demux->taglist);
      demux->taglist = gst_tag_list_new ();
      demux->push_tags = FALSE;
    }
708
709
  }

710
711
712
713
714
715
  /* Check if we have anything to push */
  if (demux->tag_data_size <= codec_data) {
    GST_LOG_OBJECT (demux, "Nothing left in this tag, returning");
    goto beach;
  }

716
  /* Create buffer from pad */
717
718
719
  outbuf =
      gst_buffer_create_sub (buffer, 7 + codec_data,
      demux->tag_data_size - codec_data);
720

721
722
723
724
725
726
727
728
729
730
731
  if (demux->audio_codec_tag == 10) {
    guint8 aac_packet_type = GST_READ_UINT8 (data + 8);

    switch (aac_packet_type) {
      case 0:
      {
        /* AudioSpecificConfic data */
        GST_LOG_OBJECT (demux, "got an AAC codec data packet");
        if (demux->audio_codec_data) {
          gst_buffer_unref (demux->audio_codec_data);
        }
732
        demux->audio_codec_data = outbuf;
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
        /* Use that buffer data in the caps */
        gst_flv_parse_audio_negotiate (demux, codec_tag, rate, channels, width);
        goto beach;
        break;
      }
      case 1:
        /* AAC raw packet */
        GST_LOG_OBJECT (demux, "got a raw AAC audio packet");
        break;
      default:
        GST_WARNING_OBJECT (demux, "invalid AAC packet type %u",
            aac_packet_type);
    }
  }

748
  /* Fill buffer with data */
749
750
751
752
753
  GST_BUFFER_TIMESTAMP (outbuf) = pts * GST_MSECOND;
  GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
  GST_BUFFER_OFFSET (outbuf) = demux->audio_offset++;
  GST_BUFFER_OFFSET_END (outbuf) = demux->audio_offset;
  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (demux->audio_pad));
754

755
  if (demux->duration == GST_CLOCK_TIME_NONE ||
756
757
      demux->duration < GST_BUFFER_TIMESTAMP (outbuf))
    demux->duration = GST_BUFFER_TIMESTAMP (outbuf);
758

759
760
761
762
763
764
765
  /* Only add audio frames to the index if we have no video, if we don't have
   * random access and if the index is not yet complete */
  if (!demux->has_video && demux->index && !demux->random_access
      && !demux->indexed) {
    GST_LOG_OBJECT (demux,
        "adding association %" GST_TIME_FORMAT "-> %" G_GUINT64_FORMAT,
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)), demux->cur_tag_offset);
766
    gst_index_add_association (demux->index, demux->index_id,
767
768
769
        GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME,
        GST_BUFFER_TIMESTAMP (outbuf), GST_FORMAT_BYTES, demux->cur_tag_offset,
        NULL);
770
771
  }

772
  if (G_UNLIKELY (demux->audio_need_discont)) {
773
    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
774
775
776
    demux->audio_need_discont = FALSE;
  }

777
  gst_segment_set_last_stop (&demux->segment, GST_FORMAT_TIME,
778
      GST_BUFFER_TIMESTAMP (outbuf));
779
780
781

  /* Do we need a newsegment event ? */
  if (G_UNLIKELY (demux->audio_need_segment)) {
782
783
784
785
    if (demux->close_seg_event)
      gst_pad_push_event (demux->audio_pad,
          gst_event_ref (demux->close_seg_event));

786
787
788
    if (!demux->new_seg_event) {
      GST_DEBUG_OBJECT (demux, "pushing newsegment from %"
          GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
789
790
          GST_TIME_ARGS (demux->segment.last_stop),
          GST_TIME_ARGS (demux->segment.stop));
791
      demux->new_seg_event =
792
793
794
          gst_event_new_new_segment (FALSE, demux->segment.rate,
          demux->segment.format, demux->segment.last_stop,
          demux->segment.stop, demux->segment.last_stop);
795
796
    } else {
      GST_DEBUG_OBJECT (demux, "pushing pre-generated newsegment event");
797
798
799
800
801
802
803
804
805
    }

    gst_pad_push_event (demux->audio_pad, gst_event_ref (demux->new_seg_event));

    demux->audio_need_segment = FALSE;
  }

  GST_LOG_OBJECT (demux, "pushing %d bytes buffer at pts %" GST_TIME_FORMAT
      " with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT,
806
807
      GST_BUFFER_SIZE (outbuf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
      GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf));
808

809
810
811
812
813
  if (!GST_CLOCK_TIME_IS_VALID (demux->audio_start)) {
    demux->audio_start = GST_BUFFER_TIMESTAMP (outbuf);
  }

  if (G_UNLIKELY (!demux->no_more_pads
814
815
          && (GST_CLOCK_DIFF (demux->audio_start,
                  GST_BUFFER_TIMESTAMP (outbuf)) > 6 * GST_SECOND))) {
816
817
818
819
820
821
822
    GST_DEBUG_OBJECT (demux,
        "Signalling no-more-pads because no video stream was found"
        " after 6 seconds of audio");
    gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
    demux->no_more_pads = TRUE;
  }

823
  /* Push downstream */
824
825
826
827
828
829
830
831
832
833
834
835
  ret = gst_pad_push (demux->audio_pad, outbuf);
  if (G_UNLIKELY (ret != GST_FLOW_OK)) {
    GST_WARNING_OBJECT (demux, "failed pushing a %" G_GUINT64_FORMAT
        " bytes audio buffer: %s", demux->tag_data_size,
        gst_flow_get_name (ret));
    if (ret == GST_FLOW_NOT_LINKED) {
      demux->audio_linked = FALSE;
    }
    goto beach;
  }

  demux->audio_linked = TRUE;
836
837
838
839
840

beach:
  return ret;
}

841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
static gboolean
gst_flv_parse_video_negotiate (GstFLVDemux * demux, guint32 codec_tag)
{
  gboolean ret = FALSE;
  GstCaps *caps = NULL;
  gchar *codec_name = NULL;

  /* Generate caps for that pad */
  switch (codec_tag) {
    case 2:
      caps = gst_caps_new_simple ("video/x-flash-video", NULL);
      codec_name = "Sorenson Video";
      break;
    case 3:
      caps = gst_caps_new_simple ("video/x-flash-screen", NULL);
      codec_name = "Flash Screen Video";
857
      break;
858
859
860
861
    case 4:
      caps = gst_caps_new_simple ("video/x-vp6-flash", NULL);
      codec_name = "On2 VP6 Video";
      break;
862
863
864
865
    case 5:
      caps = gst_caps_new_simple ("video/x-vp6-alpha", NULL);
      codec_name = "On2 VP6 Video with alpha channel";
      break;
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
    case 7:
      caps = gst_caps_new_simple ("video/x-h264", NULL);
      codec_name = "H.264/AVC Video";
      break;
    default:
      GST_WARNING_OBJECT (demux, "unsupported video codec tag %u", codec_tag);
  }

  if (G_UNLIKELY (!caps)) {
    GST_WARNING_OBJECT (demux, "failed creating caps for video pad");
    goto beach;
  }

  gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
      demux->par_x, demux->par_y, NULL);

  if (demux->video_codec_data) {
    gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
        demux->video_codec_data, NULL);
  }

  ret = gst_pad_set_caps (demux->video_pad, caps);

  if (G_LIKELY (ret)) {
    /* Store the caps we have set */
    demux->video_codec_tag = codec_tag;

    if (codec_name) {
      if (demux->taglist == NULL)
        demux->taglist = gst_tag_list_new ();
      gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
          GST_TAG_VIDEO_CODEC, codec_name, NULL);
    }

    GST_DEBUG_OBJECT (demux->video_pad, "successfully negotiated caps %"
        GST_PTR_FORMAT, caps);
  } else {
    GST_WARNING_OBJECT (demux->video_pad, "failed negotiating caps %"
        GST_PTR_FORMAT, caps);
  }

  gst_caps_unref (caps);

beach:
  return ret;
}

913
GstFlowReturn
914
gst_flv_parse_tag_video (GstFLVDemux * demux, GstBuffer * buffer)
915
916
{
  GstFlowReturn ret = GST_FLOW_OK;
917
  guint32 pts = 0, codec_data = 1, pts_ext = 0;
918
  gboolean keyframe = FALSE;
919
  guint8 flags = 0, codec_tag = 0;
920
921
  guint8 *data = GST_BUFFER_DATA (buffer);
  GstBuffer *outbuf;
922

923
924
  g_return_val_if_fail (GST_BUFFER_SIZE (buffer) == demux->tag_size,
      GST_FLOW_ERROR);
925

926
927
  GST_LOG_OBJECT (demux, "parsing a video tag");

928

929
930
931
  GST_LOG_OBJECT (demux, "pts bytes %02X %02X %02X %02X", data[0], data[1],
      data[2], data[3]);

932
933
934
935
936
937
  if (demux->no_more_pads && !demux->video_pad) {
    GST_WARNING_OBJECT (demux,
        "Signaled no-more-pads already but had no audio pad -- ignoring");
    goto beach;
  }

938
  /* Grab information about video tag */
939
  pts = GST_READ_UINT24_BE (data);
940
941
942
943
  /* read the pts extension to 32 bits integer */
  pts_ext = GST_READ_UINT8 (data + 3);
  /* Combine them */
  pts |= pts_ext << 24;
944

945
  if (GST_BUFFER_SIZE (buffer) < 12) {
946
947
948
949
    GST_ERROR_OBJECT (demux, "Too small tag size");
    return GST_FLOW_ERROR;
  }

950
  /* Skip the stream id and go directly to the flags */
951
952
953
  flags = GST_READ_UINT8 (data + 7);

  /* Keyframe */
954
  if ((flags >> 4) == 1) {
955
956
957
    keyframe = TRUE;
  }
  /* Codec tag */
958
  codec_tag = flags & 0x0F;
959
960
  if (codec_tag == 4 || codec_tag == 5) {
    codec_data = 2;
961
962
  } else if (codec_tag == 7) {
    codec_data = 5;
963
  }
964

965
966
  GST_LOG_OBJECT (demux, "video tag with codec tag %u, keyframe (%d) "
      "(flags %02X)", codec_tag, keyframe, flags);
967
968
969

  /* If we don't have our video pad created, then create it. */
  if (G_UNLIKELY (!demux->video_pad)) {
970
971
972
    demux->video_pad =
        gst_pad_new_from_template (gst_element_class_get_pad_template
        (GST_ELEMENT_GET_CLASS (demux), "video"), "video");
973
974
975
976
977
978
    if (G_UNLIKELY (!demux->video_pad)) {
      GST_WARNING_OBJECT (demux, "failed creating video pad");
      ret = GST_FLOW_ERROR;
      goto beach;
    }

979
    if (!gst_flv_parse_video_negotiate (demux, codec_tag)) {
980
981
982
983
984
985
      gst_object_unref (demux->video_pad);
      demux->video_pad = NULL;
      ret = GST_FLOW_ERROR;
      goto beach;
    }

986
987
988
989
    /* When we ve set pixel-aspect-ratio we use that boolean to detect a 
     * metadata tag that would come later and trigger a caps change */
    demux->got_par = FALSE;

990
    GST_DEBUG_OBJECT (demux, "created video pad with caps %" GST_PTR_FORMAT,
991
        GST_PAD_CAPS (demux->video_pad));
992
993
994
995
996
997

    /* Set functions on the pad */
    gst_pad_set_query_type_function (demux->video_pad,
        GST_DEBUG_FUNCPTR (gst_flv_demux_query_types));
    gst_pad_set_query_function (demux->video_pad,
        GST_DEBUG_FUNCPTR (gst_flv_demux_query));
998
999
    gst_pad_set_event_function (demux->video_pad,
        GST_DEBUG_FUNCPTR (gst_flv_demux_src_event));
1000

1001
1002
1003
1004
1005
    gst_pad_use_fixed_caps (demux->video_pad);

    /* Make it active */
    gst_pad_set_active (demux->video_pad, TRUE);

1006
    /* We need to set caps before adding */
1007
1008
1009
    gst_element_add_pad (GST_ELEMENT (demux),
        gst_object_ref (demux->video_pad));

1010
1011
1012
1013
    /* We only emit no more pads when we have audio and video. Indeed we can
     * not trust the FLV header to tell us if there will be only audio or 
     * only video and we would just break discovery of some files */
    if (demux->audio_pad && demux->video_pad) {
1014
1015
      GST_DEBUG_OBJECT (demux, "emitting no more pads");
      gst_element_no_more_pads (GST_ELEMENT (demux));
1016
      demux->no_more_pads = TRUE;
1017
    }
1018
1019
1020
  }

  /* Check if caps have changed */
1021
  if (G_UNLIKELY (codec_tag != demux->video_codec_tag || demux->got_par)) {
1022
1023
1024

    GST_DEBUG_OBJECT (demux, "video settings have changed, changing caps");

1025
1026
1027
1028
    if (!gst_flv_parse_video_negotiate (demux, codec_tag)) {
      ret = GST_FLOW_ERROR;
      goto beach;
    }
1029
1030
1031
1032

    /* When we ve set pixel-aspect-ratio we use that boolean to detect a 
     * metadata tag that would come later and trigger a caps change */
    demux->got_par = FALSE;
1033
1034
1035
  }

  /* Push taglist if present */
1036
  if ((demux->has_audio && !demux->audio_pad) &&
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
      (demux->has_video && !demux->video_pad)) {
    GST_DEBUG_OBJECT (demux, "we are still waiting for a stream to come up "
        "before we can push tags");
  } else {
    if (demux->taglist && demux->push_tags) {
      GST_DEBUG_OBJECT (demux, "pushing tags out");
      gst_element_found_tags (GST_ELEMENT (demux), demux->taglist);
      demux->taglist = gst_tag_list_new ();
      demux->push_tags = FALSE;
    }
1047
1048
  }

1049
1050
1051
1052
1053
1054
  /* Check if we have anything to push */
  if (demux->tag_data_size <= codec_data) {
    GST_LOG_OBJECT (demux, "Nothing left in this tag, returning");
    goto beach;
  }

1055
  /* Create buffer from pad */
1056
1057
1058
  outbuf =
      gst_buffer_create_sub (buffer, 7 + codec_data,
      demux->tag_data_size - codec_data);
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070

  if (demux->video_codec_tag == 7) {
    guint8 avc_packet_type = GST_READ_UINT8 (data + 8);

    switch (avc_packet_type) {
      case 0:
      {
        /* AVCDecoderConfigurationRecord data */
        GST_LOG_OBJECT (demux, "got an H.264 codec data packet");
        if (demux->video_codec_data) {
          gst_buffer_unref (demux->video_codec_data);
        }
1071
        demux->video_codec_data = outbuf;
1072
1073
1074
1075
1076
1077
1078
        /* Use that buffer data in the caps */
        gst_flv_parse_video_negotiate (demux, codec_tag);
        goto beach;
        break;
      }
      case 1:
        /* H.264 NALU packet */
1079
        GST_LOG_OBJECT (demux, "got a H.264 NALU video packet");
1080
1081
        break;
      default:
1082
        GST_WARNING_OBJECT (demux, "invalid video packet type %u",
1083
1084
1085
1086
            avc_packet_type);
    }
  }

1087
  /* Fill buffer with data */
1088
1089
1090
1091
1092
  GST_BUFFER_TIMESTAMP (outbuf) = pts * GST_MSECOND;
  GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
  GST_BUFFER_OFFSET (outbuf) = demux->video_offset++;
  GST_BUFFER_OFFSET_END (outbuf) = demux->video_offset;
  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (demux->video_pad));
1093

1094
  if (demux->duration == GST_CLOCK_TIME_NONE ||
1095
1096
      demux->duration < GST_BUFFER_TIMESTAMP (outbuf))
    demux->duration = GST_BUFFER_TIMESTAMP (outbuf);
1097

1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
  if (!demux->indexed) {
    if (!keyframe) {
      GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
      if (demux->index && !demux->random_access) {
        GST_LOG_OBJECT (demux, "adding association %" GST_TIME_FORMAT "-> %"
            G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
            demux->cur_tag_offset);
        gst_index_add_association (demux->index, demux->index_id,
            GST_ASSOCIATION_FLAG_NONE,
            GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (outbuf),
            GST_FORMAT_BYTES, demux->cur_tag_offset, NULL);
      }
    } else {
      if (demux->index && !demux->random_access) {
        GST_LOG_OBJECT (demux, "adding association %" GST_TIME_FORMAT "-> %"
            G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
            demux->cur_tag_offset);
        gst_index_add_association (demux->index, demux->index_id,
            GST_ASSOCIATION_FLAG_KEY_UNIT,
            GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (outbuf),
            GST_FORMAT_BYTES, demux->cur_tag_offset, NULL);
      }
1120
    }
1121
1122
1123
  }

  if (G_UNLIKELY (demux->video_need_discont)) {
1124
    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
1125
1126
1127
    demux->video_need_discont = FALSE;
  }

1128
  gst_segment_set_last_stop (&demux->segment, GST_FORMAT_TIME,
1129
      GST_BUFFER_TIMESTAMP (outbuf));
1130
1131
1132

  /* Do we need a newsegment event ? */
  if (G_UNLIKELY (demux->video_need_segment)) {
1133
1134
1135
1136
    if (demux->close_seg_event)
      gst_pad_push_event (demux->video_pad,
          gst_event_ref (demux->close_seg_event));

1137
1138
1139
    if (!demux->new_seg_event) {
      GST_DEBUG_OBJECT (demux, "pushing newsegment from %"
          GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
1140
1141
          GST_TIME_ARGS (demux->segment.last_stop),
          GST_TIME_ARGS (demux->segment.stop));
1142
      demux->new_seg_event =
1143
1144
1145
          gst_event_new_new_segment (FALSE, demux->segment.rate,
          demux->segment.format, demux->segment.last_stop,
          demux->segment.stop, demux->segment.last_stop);
1146
1147
    } else {
      GST_DEBUG_OBJECT (demux, "pushing pre-generated newsegment event");
1148
1149
1150
1151
1152
1153
1154
1155
1156
    }

    gst_pad_push_event (demux->video_pad, gst_event_ref (demux->new_seg_event));

    demux->video_need_segment = FALSE;
  }

  GST_LOG_OBJECT (demux, "pushing %d bytes buffer at pts %" GST_TIME_FORMAT
      " with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT
1157
1158
1159
      ", keyframe (%d)", GST_BUFFER_SIZE (outbuf),
      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
      GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf),
1160
1161
      keyframe);

1162
1163
1164
1165
1166
  if (!GST_CLOCK_TIME_IS_VALID (demux->video_start)) {
    demux->video_start = GST_BUFFER_TIMESTAMP (outbuf);
  }

  if (G_UNLIKELY (!demux->no_more_pads
1167
1168
          && (GST_CLOCK_DIFF (demux->video_start,
                  GST_BUFFER_TIMESTAMP (outbuf)) > 6 * GST_SECOND))) {
1169
1170
1171
1172
1173
1174
1175
    GST_DEBUG_OBJECT (demux,
        "Signalling no-more-pads because no audio stream was found"
        " after 6 seconds of video");
    gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
    demux->no_more_pads = TRUE;
  }

1176
  /* Push downstream */
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
  ret = gst_pad_push (demux->video_pad, outbuf);

  if (G_UNLIKELY (ret != GST_FLOW_OK)) {
    GST_WARNING_OBJECT (demux, "failed pushing a %" G_GUINT64_FORMAT
        " bytes video buffer: %s", demux->tag_data_size,
        gst_flow_get_name (ret));
    if (ret == GST_FLOW_NOT_LINKED) {
      demux->video_linked = FALSE;
    }
    goto beach;
  }

  demux->video_linked = TRUE;
1190
1191
1192
1193
1194

beach:
  return ret;
}

1195
GstClockTime
1196
1197
gst_flv_parse_tag_timestamp (GstFLVDemux * demux, GstBuffer * buffer,
    size_t * tag_size)
1198
1199
{
  guint32 pts = 0, pts_ext = 0;
1200
1201
1202
1203
  guint32 tag_data_size;
  guint8 type;
  gboolean keyframe = TRUE;
  GstClockTime ret;
1204
  guint8 *data = GST_BUFFER_DATA (buffer);
1205