riff-media.c 53.5 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* GStreamer RIFF I/O
 * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
 *
 * riff-media.h: RIFF-id to/from caps routines
 *
 * 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.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "riff-ids.h"
#include "riff-media.h"

29
30
31
#include <gst/audio/multichannel.h>

#include <string.h>
32
#include <math.h>
33
34
35
36

GST_DEBUG_CATEGORY_EXTERN (riff_debug);
#define GST_CAT_DEFAULT riff_debug

37
/**
38
 * gst_riff_create_video_caps:
39
40
41
42
43
44
45
46
47
48
49
50
 * @codec_fcc: fourCC codec for this codec.
 * @strh: pointer to the strh stream header structure.
 * @strf: pointer to the strf stream header structure, including any
 *        data that is within the range of strf.size, but excluding any
 *        additional data withint this chunk but outside strf.size.
 * @strf_data: a #GstBuffer containing the additional data in the strf
 *             chunk outside reach of strf.size. Ususally a palette.
 * @strd_data: a #GstBuffer containing the data in the strd stream header
 *             chunk. Usually codec initialization data.
 * @codec_name: if given, will be filled with a human-readable codec name.
 */

51
GstCaps *
52
gst_riff_create_video_caps (guint32 codec_fcc,
53
54
    gst_riff_strh * strh, gst_riff_strf_vids * strf,
    GstBuffer * strf_data, GstBuffer * strd_data, char **codec_name)
55
56
{
  GstCaps *caps = NULL;
57
  GstBuffer *palette = NULL;
58

59
60
  GST_DEBUG ("video fourcc %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (codec_fcc));

61
  switch (codec_fcc) {
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
    case GST_MAKE_FOURCC ('D', 'I', 'B', ' '):{
      gint bpp = (strf && strf->bit_cnt != 0) ? strf->bit_cnt : 8;

      if (strf) {
        if (bpp == 8) {
          caps = gst_caps_new_simple ("video/x-raw-rgb",
              "bpp", G_TYPE_INT, 8, "depth", G_TYPE_INT, 8,
              "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL);
        } else if (bpp == 24) {
          caps = gst_caps_new_simple ("video/x-raw-rgb",
              "bpp", G_TYPE_INT, 24, "depth", G_TYPE_INT, 24,
              "endianness", G_TYPE_INT, G_BIG_ENDIAN,
              "red_mask", G_TYPE_INT, 0xff, "green_mask", G_TYPE_INT, 0xff00,
              "blue_mask", G_TYPE_INT, 0xff0000, NULL);
        } else {
          GST_WARNING ("Unhandled DIB RGB depth: %d", bpp);
78
          return NULL;
79
80
81
82
83
84
85
        }
      } else {
        /* for template */
        caps = gst_caps_from_string ("video/x-raw-rgb, bpp = (int) { 8, 24 }, "
            "depth = (int) { 8, 24}");
      }

86
87
88
      palette = strf_data;
      strf_data = NULL;
      if (codec_name)
89
        *codec_name = g_strdup_printf ("Palettized %d-bit RGB", bpp);
90
      break;
91
    }
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
92
    case GST_MAKE_FOURCC ('I', '4', '2', '0'):
93
      caps = gst_caps_new_simple ("video/x-raw-yuv",
94
          "format", GST_TYPE_FOURCC, codec_fcc, NULL);
95
      if (codec_name)
96
        *codec_name = g_strdup ("Uncompressed planar YUV 4:2:0");
97
      break;
98

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
99
    case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
David Schleef's avatar
David Schleef committed
100
      caps = gst_caps_new_simple ("video/x-raw-yuv",
101
          "format", GST_TYPE_FOURCC, codec_fcc, NULL);
102
      if (codec_name)
103
        *codec_name = g_strdup ("Uncompressed packed YUV 4:2:2");
104
105
      break;

106
107
108
109
110
111
112
    case GST_MAKE_FOURCC ('Y', 'V', 'U', '9'):
      caps = gst_caps_new_simple ("video/x-raw-yuv",
          "format", GST_TYPE_FOURCC, codec_fcc, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Uncompressed packed YVU 4:1:0");
      break;

113
    case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'): /* YUY2 MJPEG */
114
115
116
117
    case GST_MAKE_FOURCC ('A', 'V', 'R', 'n'):
    case GST_MAKE_FOURCC ('I', 'J', 'P', 'G'):
    case GST_MAKE_FOURCC ('i', 'j', 'p', 'g'):
    case GST_MAKE_FOURCC ('J', 'P', 'G', 'L'):
118
      caps = gst_caps_new_simple ("image/jpeg", NULL);
119
      if (codec_name)
120
        *codec_name = g_strdup ("Motion JPEG");
121
      break;
122

123
    case GST_MAKE_FOURCC ('J', 'P', 'E', 'G'): /* generic (mostly RGB) MJPEG */
124
    case GST_MAKE_FOURCC ('j', 'p', 'e', 'g'): /* generic (mostly RGB) MJPEG */
125
      caps = gst_caps_new_simple ("image/jpeg", NULL);
126
      if (codec_name)
127
        *codec_name = g_strdup ("JPEG Still Image");
128
      break;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
129

130
131
    case GST_MAKE_FOURCC ('P', 'I', 'X', 'L'): /* Miro/Pinnacle fourccs */
    case GST_MAKE_FOURCC ('V', 'I', 'X', 'L'): /* Miro/Pinnacle fourccs */
132
      caps = gst_caps_new_simple ("image/jpeg", NULL);
133
      if (codec_name)
134
        *codec_name = g_strdup ("Miro/Pinnacle Motion JPEG Video");
135
      break;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
136

137
138
139
140
141
142
143
144
145
146
147
    case GST_MAKE_FOURCC ('S', 'P', '5', '3'):
    case GST_MAKE_FOURCC ('S', 'P', '5', '4'):
    case GST_MAKE_FOURCC ('S', 'P', '5', '5'):
    case GST_MAKE_FOURCC ('S', 'P', '5', '6'):
    case GST_MAKE_FOURCC ('S', 'P', '5', '7'):
    case GST_MAKE_FOURCC ('S', 'P', '5', '8'):
      caps = gst_caps_new_simple ("video/sp5x", NULL);
      if (codec_name)
        *codec_name = g_strdup ("Sp5x-like JPEG");
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
148
149
    case GST_MAKE_FOURCC ('H', 'F', 'Y', 'U'):
      caps = gst_caps_new_simple ("video/x-huffyuv", NULL);
150
151
152
153
      if (strf) {
        gst_caps_set_simple (caps, "bpp",
            G_TYPE_INT, (int) strf->bit_cnt, NULL);
      }
154
      if (codec_name)
155
        *codec_name = g_strdup ("Huffman Lossless Codec");
156
      break;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
157
158
159

    case GST_MAKE_FOURCC ('M', 'P', 'E', 'G'):
    case GST_MAKE_FOURCC ('M', 'P', 'G', 'I'):
160
161
    case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
    case GST_MAKE_FOURCC ('M', 'P', 'G', '1'):
162
    case GST_MAKE_FOURCC ('P', 'I', 'M', '1'):
David Schleef's avatar
David Schleef committed
163
      caps = gst_caps_new_simple ("video/mpeg",
164
          "systemstream", G_TYPE_BOOLEAN, FALSE,
165
          "mpegversion", G_TYPE_INT, 1, NULL);
166
      if (codec_name)
167
        *codec_name = g_strdup ("MPEG-1 video");
168
      break;
169
170
171
172
173
174
    case GST_MAKE_FOURCC ('M', 'P', 'G', '2'):
    case GST_MAKE_FOURCC ('m', 'p', 'g', '2'):
      caps = gst_caps_new_simple ("video/mpeg",
          "systemstream", G_TYPE_BOOLEAN, FALSE,
          "mpegversion", G_TYPE_INT, 2, NULL);
      if (codec_name)
175
        *codec_name = g_strdup ("MPEG-2 video");
176
      break;
177

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
178
    case GST_MAKE_FOURCC ('H', '2', '6', '3'):
179
    case GST_MAKE_FOURCC ('h', '2', '6', '3'):
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
180
    case GST_MAKE_FOURCC ('i', '2', '6', '3'):
181
    case GST_MAKE_FOURCC ('U', '2', '6', '3'):
182
183
      caps = gst_caps_new_simple ("video/x-h263",
          "variant", G_TYPE_STRING, "itu", NULL);
184
      if (codec_name)
185
        *codec_name = g_strdup ("ITU H.26n");
186
      break;
187

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
188
    case GST_MAKE_FOURCC ('L', '2', '6', '3'):
189
190
191
      /* http://www.leadcodecs.com/Codecs/LEAD-H263.htm */
      caps = gst_caps_new_simple ("video/x-h263",
          "variant", G_TYPE_STRING, "lead", NULL);
192
      if (codec_name)
193
        *codec_name = g_strdup ("Lead H.263");
194
      break;
195

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
196
    case GST_MAKE_FOURCC ('M', '2', '6', '3'):
197
    case GST_MAKE_FOURCC ('m', '2', '6', '3'):
198
199
      caps = gst_caps_new_simple ("video/x-h263",
          "variant", G_TYPE_STRING, "microsoft", NULL);
200
      if (codec_name)
201
        *codec_name = g_strdup ("Microsoft H.263");
202
      break;
203

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
204
    case GST_MAKE_FOURCC ('V', 'D', 'O', 'W'):
205
206
      caps = gst_caps_new_simple ("video/x-h263",
          "variant", G_TYPE_STRING, "vdolive", NULL);
207
      if (codec_name)
208
        *codec_name = g_strdup ("VDOLive");
209
      break;
210

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
211
    case GST_MAKE_FOURCC ('V', 'I', 'V', 'O'):
212
213
      caps = gst_caps_new_simple ("video/x-h263",
          "variant", G_TYPE_STRING, "vivo", NULL);
214
      if (codec_name)
215
        *codec_name = g_strdup ("Vivo H.263");
216
      break;
217

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
218
    case GST_MAKE_FOURCC ('x', '2', '6', '3'):
219
220
      caps = gst_caps_new_simple ("video/x-h263",
          "variant", G_TYPE_STRING, "xirlink", NULL);
221
      if (codec_name)
222
        *codec_name = g_strdup ("Xirlink H.263");
223
224
      break;

225
226
      /* apparently not standard H.263...? */
    case GST_MAKE_FOURCC ('I', '2', '6', '3'):
227
228
      caps = gst_caps_new_simple ("video/x-intel-h263",
          "variant", G_TYPE_STRING, "intel", NULL);
229
230
231
232
      if (codec_name)
        *codec_name = g_strdup ("Intel H.263");
      break;

233
    case GST_MAKE_FOURCC ('H', '2', '6', '4'):
234
    case GST_MAKE_FOURCC ('h', '2', '6', '4'):
235
236
    case GST_MAKE_FOURCC ('a', 'v', 'c', '1'):
    case GST_MAKE_FOURCC ('A', 'V', 'C', '1'):
237
238
      caps = gst_caps_new_simple ("video/x-h264",
          "variant", G_TYPE_STRING, "itu", NULL);
239
240
241
242
243
      if (codec_name)
        *codec_name = g_strdup ("ITU H.264");
      break;

    case GST_MAKE_FOURCC ('V', 'S', 'S', 'H'):
244
245
      caps = gst_caps_new_simple ("video/x-h264",
          "variant", G_TYPE_STRING, "videosoft", NULL);
246
247
248
249
      if (codec_name)
        *codec_name = g_strdup ("VideoSoft H.264");
      break;

250
251
252
253
254
255
256
257
    case GST_MAKE_FOURCC ('L', '2', '6', '4'):
      /* http://www.leadcodecs.com/Codecs/LEAD-H264.htm */
      caps = gst_caps_new_simple ("video/x-h264",
          "variant", G_TYPE_STRING, "lead", NULL);
      if (codec_name)
        *codec_name = g_strdup ("Lead H.264");
      break;

258
259
260
261
262
263
264
    case GST_MAKE_FOURCC ('S', 'E', 'D', 'G'):
      caps = gst_caps_new_simple ("video/mpeg",
          "mpegversion", G_TYPE_INT, 4, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Samsung MPEG-4");
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
265
    case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
266
    case GST_MAKE_FOURCC ('d', 'i', 'v', '3'):
267
    case GST_MAKE_FOURCC ('D', 'I', 'V', '4'):
268
    case GST_MAKE_FOURCC ('d', 'i', 'v', '4'):
269
    case GST_MAKE_FOURCC ('D', 'I', 'V', '5'):
270
    case GST_MAKE_FOURCC ('d', 'i', 'v', '5'):
271
    case GST_MAKE_FOURCC ('D', 'I', 'V', '6'):
272
    case GST_MAKE_FOURCC ('d', 'i', 'v', '6'):
273
274
275
276
277
278
279
    case GST_MAKE_FOURCC ('M', 'P', 'G', '3'):
    case GST_MAKE_FOURCC ('m', 'p', 'g', '3'):
    case GST_MAKE_FOURCC ('c', 'o', 'l', '0'):
    case GST_MAKE_FOURCC ('C', 'O', 'L', '0'):
    case GST_MAKE_FOURCC ('c', 'o', 'l', '1'):
    case GST_MAKE_FOURCC ('C', 'O', 'L', '1'):
    case GST_MAKE_FOURCC ('A', 'P', '4', '1'):
David Schleef's avatar
David Schleef committed
280
      caps = gst_caps_new_simple ("video/x-divx",
281
          "divxversion", G_TYPE_INT, 3, NULL);
282
      if (codec_name)
283
        *codec_name = g_strdup ("DivX MS-MPEG-4 Version 3");
284
      break;
285

286
287
    case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
    case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
288
      caps = gst_caps_new_simple ("video/x-divx",
289
          "divxversion", G_TYPE_INT, 4, NULL);
290
      if (codec_name)
291
        *codec_name = g_strdup ("DivX MPEG-4 Version 4");
292
      break;
293

294
295
296
297
298
299
300
    case GST_MAKE_FOURCC ('B', 'L', 'Z', '0'):
      caps = gst_caps_new_simple ("video/x-divx",
          "divxversion", G_TYPE_INT, 4, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Blizzard DivX");
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
301
    case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
David Schleef's avatar
David Schleef committed
302
      caps = gst_caps_new_simple ("video/x-divx",
303
          "divxversion", G_TYPE_INT, 5, NULL);
304
      if (codec_name)
305
        *codec_name = g_strdup ("DivX MPEG-4 Version 5");
306
307
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
308
309
    case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
    case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
David Schleef's avatar
David Schleef committed
310
      caps = gst_caps_new_simple ("video/x-xvid", NULL);
311
      if (codec_name)
312
        *codec_name = g_strdup ("XVID MPEG-4");
313
314
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
315
    case GST_MAKE_FOURCC ('M', 'P', 'G', '4'):
David Schleef's avatar
David Schleef committed
316
      caps = gst_caps_new_simple ("video/x-msmpeg",
317
          "msmpegversion", G_TYPE_INT, 41, NULL);
318
      if (codec_name)
319
        *codec_name = g_strdup ("Microsoft MPEG-4 4.1");
320
321
      break;

322
    case GST_MAKE_FOURCC ('m', 'p', '4', '2'):
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
323
    case GST_MAKE_FOURCC ('M', 'P', '4', '2'):
David Schleef's avatar
David Schleef committed
324
      caps = gst_caps_new_simple ("video/x-msmpeg",
325
          "msmpegversion", G_TYPE_INT, 42, NULL);
326
      if (codec_name)
327
        *codec_name = g_strdup ("Microsoft MPEG-4 4.2");
328
329
      break;

330
    case GST_MAKE_FOURCC ('m', 'p', '4', '3'):
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
331
    case GST_MAKE_FOURCC ('M', 'P', '4', '3'):
David Schleef's avatar
David Schleef committed
332
      caps = gst_caps_new_simple ("video/x-msmpeg",
333
          "msmpegversion", G_TYPE_INT, 43, NULL);
334
      if (codec_name)
335
        *codec_name = g_strdup ("Microsoft MPEG-4 4.3");
336
337
      break;

338
    case GST_MAKE_FOURCC ('M', 'P', '4', 'S'):
339
340
341
342
343
344
345
346
    case GST_MAKE_FOURCC ('M', '4', 'S', '2'):
      caps = gst_caps_new_simple ("video/mpeg",
          "mpegversion", G_TYPE_INT, 4, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Microsoft ISO MPEG-4 1.1");
      break;

    case GST_MAKE_FOURCC ('F', 'M', 'P', '4'):
347
    case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
348
349
350
351
352
353
      caps = gst_caps_new_simple ("video/mpeg",
          "mpegversion", G_TYPE_INT, 4, NULL);
      if (codec_name)
        *codec_name = g_strdup ("FFmpeg MPEG-4");
      break;

354
355
    case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
    case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
356
357
      caps = gst_caps_new_simple ("video/x-msmpeg",
          "msmpegversion", G_TYPE_INT, 43, NULL);
358
359
      if (codec_name)
        *codec_name = g_strdup ("Microsoft MPEG-4 4.3");        /* FIXME? */
360
      break;
361

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
362
363
364
    case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
    case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
      caps = gst_caps_new_simple ("video/x-3ivx", NULL);
365
      if (codec_name)
366
        *codec_name = g_strdup ("3ivx");
367
368
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
369
370
    case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
    case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
371
    case GST_MAKE_FOURCC ('C', 'D', 'V', 'C'):
David Schleef's avatar
David Schleef committed
372
      caps = gst_caps_new_simple ("video/x-dv",
373
374
          "systemstream", G_TYPE_BOOLEAN, FALSE,
          "dvversion", G_TYPE_INT, 25, NULL);
375
      if (codec_name)
376
        *codec_name = g_strdup ("Generic DV");
377
378
      break;

379
380
381
382
383
384
385
386
387
    case GST_MAKE_FOURCC ('D', 'V', '5', '0'):
    case GST_MAKE_FOURCC ('d', 'v', '5', '0'):
      caps = gst_caps_new_simple ("video/x-dv",
          "systemstream", G_TYPE_BOOLEAN, FALSE,
          "dvversion", G_TYPE_INT, 50, NULL);
      if (codec_name)
        *codec_name = g_strdup ("DVCPro50 Video");
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
388
    case GST_MAKE_FOURCC ('W', 'M', 'V', '1'):
David Schleef's avatar
David Schleef committed
389
      caps = gst_caps_new_simple ("video/x-wmv",
390
          "wmvversion", G_TYPE_INT, 1, NULL);
391
      if (codec_name)
392
        *codec_name = g_strdup ("Microsoft Windows Media 7");
393
394
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
395
    case GST_MAKE_FOURCC ('W', 'M', 'V', '2'):
David Schleef's avatar
David Schleef committed
396
      caps = gst_caps_new_simple ("video/x-wmv",
397
          "wmvversion", G_TYPE_INT, 2, NULL);
398
      if (codec_name)
399
        *codec_name = g_strdup ("Microsoft Windows Media 8");
400
      break;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
401
402

    case GST_MAKE_FOURCC ('W', 'M', 'V', '3'):
403
      caps = gst_caps_new_simple ("video/x-wmv",
404
          "wmvversion", G_TYPE_INT, 3, NULL);
405
      if (codec_name)
406
        *codec_name = g_strdup ("Microsoft Windows Media 9");
407
408
      break;

409
410
411
412
413
414
415
416
    case GST_MAKE_FOURCC ('W', 'M', 'V', 'A'):
      caps = gst_caps_new_simple ("video/x-wmv",
          "wmvversion", G_TYPE_INT, 3, "fourcc", GST_TYPE_FOURCC,
          codec_fcc, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Microsoft Windows Media Advanced Profile");
      break;

417
418
419
420
421
422
423
424
    case GST_MAKE_FOURCC ('W', 'V', 'C', '1'):
      caps = gst_caps_new_simple ("video/x-wmv",
          "wmvversion", G_TYPE_INT, 3, "fourcc", GST_TYPE_FOURCC,
          codec_fcc, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Microsoft Windows Media VC-1");
      break;

425
426
427
428
429
430
    case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
      caps = gst_caps_new_simple ("video/x-cinepak", NULL);
      if (codec_name)
        *codec_name = g_strdup ("Cinepak video");
      break;

431
432
433
434
435
436
437
438
439
440
    case GST_MAKE_FOURCC ('M', 'S', 'V', 'C'):
    case GST_MAKE_FOURCC ('m', 's', 'v', 'c'):
    case GST_MAKE_FOURCC ('C', 'R', 'A', 'M'):
    case GST_MAKE_FOURCC ('c', 'r', 'a', 'm'):
    case GST_MAKE_FOURCC ('W', 'H', 'A', 'M'):
    case GST_MAKE_FOURCC ('w', 'h', 'a', 'm'):
      caps = gst_caps_new_simple ("video/x-msvideocodec",
          "msvideoversion", G_TYPE_INT, 1, NULL);
      if (codec_name)
        *codec_name = g_strdup ("MS video v1");
441
442
      palette = strf_data;
      strf_data = NULL;
443
444
      break;

445
446
447
448
449
    case GST_MAKE_FOURCC ('R', 'L', 'E', ' '):
    case GST_MAKE_FOURCC ('m', 'r', 'l', 'e'):
    case GST_MAKE_FOURCC (0x1, 0x0, 0x0, 0x0): /* why, why, why? */
      caps = gst_caps_new_simple ("video/x-rle",
          "layout", G_TYPE_STRING, "microsoft", NULL);
450
451
      palette = strf_data;
      strf_data = NULL;
452
453
454
455
456
457
458
      if (strf) {
        gst_caps_set_simple (caps,
            "depth", G_TYPE_INT, (gint) strf->bit_cnt, NULL);
      } else {
        gst_caps_set_simple (caps, "depth", GST_TYPE_INT_RANGE, 1, 64, NULL);
      }
      if (codec_name)
459
460
461
462
463
464
465
466
        *codec_name = g_strdup ("Microsoft RLE");
      break;

    case GST_MAKE_FOURCC ('X', 'x', 'a', 'n'):
      caps = gst_caps_new_simple ("video/x-xan",
          "wcversion", G_TYPE_INT, 4, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Xan Wing Commander 4");
467
468
      break;

469
470
471
472
473
474
475
476
    case GST_MAKE_FOURCC ('R', 'T', '2', '1'):
      caps = gst_caps_new_simple ("video/x-indeo",
          "indeoversion", G_TYPE_INT, 2, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Intel Video 2");
      break;

    case GST_MAKE_FOURCC ('I', 'V', '3', '1'):
477
    case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
478
479
    case GST_MAKE_FOURCC ('i', 'v', '3', '1'):
    case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
480
481
482
483
484
485
      caps = gst_caps_new_simple ("video/x-indeo",
          "indeoversion", G_TYPE_INT, 3, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Intel Video 3");
      break;

486
487
488
489
490
491
492
493
    case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
    case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
      caps = gst_caps_new_simple ("video/x-indeo",
          "indeoversion", G_TYPE_INT, 4, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Intel Video 4");
      break;

494
    case GST_MAKE_FOURCC ('I', 'V', '5', '0'):
495
496
      caps = gst_caps_new_simple ("video/x-indeo",
          "indeoversion", G_TYPE_INT, 5, NULL);
497
498
499
500
      if (codec_name)
        *codec_name = g_strdup ("Intel Video 5");
      break;

501
502
503
504
505
506
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
553
554
555
556
    case GST_MAKE_FOURCC ('M', 'S', 'Z', 'H'):
      caps = gst_caps_new_simple ("video/x-mszh", NULL);
      if (codec_name)
        *codec_name = g_strdup ("Lossless MSZH Video");
      break;

    case GST_MAKE_FOURCC ('Z', 'L', 'I', 'B'):
      caps = gst_caps_new_simple ("video/x-zlib", NULL);
      if (codec_name)
        *codec_name = g_strdup ("Lossless zlib video");
      break;

    case GST_MAKE_FOURCC ('C', 'L', 'J', 'R'):
      caps = gst_caps_new_simple ("video/x-cirrus-logic-accupak", NULL);
      if (codec_name)
        *codec_name = g_strdup ("Cirrus Logipak AccuPak");
      break;

    case GST_MAKE_FOURCC ('C', 'Y', 'U', 'V'):
    case GST_MAKE_FOURCC ('c', 'y', 'u', 'v'):
      caps = gst_caps_new_simple ("video/x-compressed-yuv", NULL);
      if (codec_name)
        *codec_name = g_strdup ("CYUV Lossless");
      break;

    case GST_MAKE_FOURCC ('D', 'U', 'C', 'K'):
      caps = gst_caps_new_simple ("video/x-truemotion",
          "trueversion", G_TYPE_INT, 1, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Duck Truemotion1");
      break;

    case GST_MAKE_FOURCC ('T', 'M', '2', '0'):
      caps = gst_caps_new_simple ("video/x-truemotion",
          "trueversion", G_TYPE_INT, 2, NULL);
      if (codec_name)
        *codec_name = g_strdup ("TrueMotion 2.0");
      break;

    case GST_MAKE_FOURCC ('V', 'P', '3', '0'):
    case GST_MAKE_FOURCC ('v', 'p', '3', '0'):
    case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
    case GST_MAKE_FOURCC ('v', 'p', '3', '1'):
    case GST_MAKE_FOURCC ('V', 'P', '3', ' '):
      caps = gst_caps_new_simple ("video/x-vp3", NULL);
      if (codec_name)
        *codec_name = g_strdup ("VP3");
      break;

    case GST_MAKE_FOURCC ('U', 'L', 'T', 'I'):
      caps = gst_caps_new_simple ("video/x-ultimotion", NULL);
      if (codec_name)
        *codec_name = g_strdup ("IBM UltiMotion");
      break;

    case GST_MAKE_FOURCC ('T', 'S', 'C', 'C'):
557
558
    case GST_MAKE_FOURCC ('t', 's', 'c', 'c'):{
      if (strf) {
559
        gint depth = (strf->bit_cnt != 0) ? (gint) strf->bit_cnt : 24;
560

561
562
        caps = gst_caps_new_simple ("video/x-camtasia", "depth", G_TYPE_INT,
            depth, NULL);
563
564
565
566
      } else {
        /* template caps */
        caps = gst_caps_new_simple ("video/x-camtasia", NULL);
      }
567
568
569
      if (codec_name)
        *codec_name = g_strdup ("TechSmith Camtasia");
      break;
570
    }
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607

    case GST_MAKE_FOURCC ('V', 'C', 'R', '1'):
      caps = gst_caps_new_simple ("video/x-ati-vcr",
          "vcrversion", G_TYPE_INT, 1, NULL);
      if (codec_name)
        *codec_name = g_strdup ("ATI VCR 1");
      break;

    case GST_MAKE_FOURCC ('V', 'C', 'R', '2'):
      caps = gst_caps_new_simple ("video/x-ati-vcr",
          "vcrversion", G_TYPE_INT, 2, NULL);
      if (codec_name)
        *codec_name = g_strdup ("ATI VCR 2");
      break;

    case GST_MAKE_FOURCC ('A', 'S', 'V', '1'):
      caps = gst_caps_new_simple ("video/x-asus",
          "asusversion", G_TYPE_INT, 1, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Asus Video 1");
      break;

    case GST_MAKE_FOURCC ('A', 'S', 'V', '2'):
      caps = gst_caps_new_simple ("video/x-asus",
          "asusversion", G_TYPE_INT, 2, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Asus Video 2");
      break;

    case GST_MAKE_FOURCC ('M', 'P', 'N', 'G'):
    case GST_MAKE_FOURCC ('m', 'p', 'n', 'g'):
    case GST_MAKE_FOURCC ('P', 'N', 'G', ' '):
      caps = gst_caps_new_simple ("image/png", NULL);
      if (codec_name)
        *codec_name = g_strdup ("PNG image");
      break;

608
609
610
611
612
613
614
    case GST_MAKE_FOURCC ('F', 'L', 'V', '1'):
      caps = gst_caps_new_simple ("video/x-flash-video",
          "flvversion", G_TYPE_INT, 1, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Flash Video 1");
      break;

615
616
617
618
619
620
621
    case GST_MAKE_FOURCC ('V', 'M', 'n', 'c'):
      caps = gst_caps_new_simple ("video/x-vmnc",
          "version", G_TYPE_INT, 1, NULL);
      if (codec_name)
        *codec_name = g_strdup ("VMWare NC Video");
      break;

622
623
624
625
626
627
    case GST_MAKE_FOURCC ('d', 'r', 'a', 'c'):
      caps = gst_caps_new_simple ("video/x-dirac", NULL);
      if (codec_name)
        *codec_name = g_strdup ("Dirac");
      break;

628
    default:
629
      GST_WARNING ("Unknown video fourcc %" GST_FOURCC_FORMAT,
630
          GST_FOURCC_ARGS (codec_fcc));
David Schleef's avatar
David Schleef committed
631
      return NULL;
632
633
  }

David Schleef's avatar
David Schleef committed
634
  if (strh != NULL) {
635
636
    gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
        strh->rate, strh->scale, NULL);
David Schleef's avatar
David Schleef committed
637
638
  } else {
    gst_caps_set_simple (caps,
639
        "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
David Schleef's avatar
David Schleef committed
640
641
642
643
  }

  if (strf != NULL) {
    gst_caps_set_simple (caps,
644
645
        "width", G_TYPE_INT, strf->width,
        "height", G_TYPE_INT, strf->height, NULL);
David Schleef's avatar
David Schleef committed
646
647
  } else {
    gst_caps_set_simple (caps,
648
649
        "width", GST_TYPE_INT_RANGE, 16, 4096,
        "height", GST_TYPE_INT_RANGE, 16, 4096, NULL);
650
651
  }

652
653
654
655
656
657
  /* extradata */
  if (strf_data || strd_data) {
    gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
        strf_data ? strf_data : strd_data, NULL);
  }

658
  /* palette */
659
660
661
662
663
664
665
666
667
  if (palette) {
    GstBuffer *copy;
    guint num_colors;

    if (strf != NULL)
      num_colors = strf->num_colors;
    else
      num_colors = 256;

668
669
    if (GST_BUFFER_SIZE (palette) >= (num_colors * 4)) {
      /* palette is always at least 256*4 bytes */
670
671
      copy =
          gst_buffer_new_and_alloc (MAX (GST_BUFFER_SIZE (palette), 256 * 4));
672
673
      memcpy (GST_BUFFER_DATA (copy), GST_BUFFER_DATA (palette),
          GST_BUFFER_SIZE (palette));
674
675

#if (G_BYTE_ORDER == G_BIG_ENDIAN)
676
677
678
679
680
681
682
683
684
685
      {
        guint8 *data = GST_BUFFER_DATA (copy);
        gint n;

        /* own endianness */
        for (n = 0; n < num_colors; n++) {
          GST_WRITE_UINT32_BE (data, GST_READ_UINT32_LE (data));
          data += sizeof (guint32);
        }
      }
686
#endif
687
688
689
690
691
      gst_caps_set_simple (caps, "palette_data", GST_TYPE_BUFFER, copy, NULL);
      gst_buffer_unref (copy);
    } else {
      GST_WARNING ("Palette smaller than expected: broken file");
    }
692
693
  }

694
695
696
  return caps;
}

697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
static const struct
{
  const guint32 ms_mask;
  const GstAudioChannelPosition gst_pos;
} layout_mapping[] = {
  {
  0x00001, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, {
  0x00002, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {
  0x00004, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, {
  0x00008, GST_AUDIO_CHANNEL_POSITION_LFE}, {
  0x00010, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT}, {
  0x00020, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
  0x00040, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, {
  0x00080, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, {
  0x00100, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, {
  0x00200, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT}, {
  0x00400, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}, {
  0x00800, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_CENTER       */
  {
  0x01000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_FRONT_LEFT   */
  {
  0x02000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_FRONT_CENTER */
  {
  0x04000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_FRONT_RIGHT  */
  {
  0x08000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_BACK_LEFT    */
  {
  0x10000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_BACK_CENTER  */
  {
  0x20000, GST_AUDIO_CHANNEL_POSITION_INVALID}  /* TOP_BACK_RIGHT   */
};

#define MAX_CHANNEL_POSITIONS G_N_ELEMENTS (layout_mapping)

static gboolean
gst_riff_wavext_add_channel_layout (GstCaps * caps, guint32 layout)
{
  GstAudioChannelPosition pos[MAX_CHANNEL_POSITIONS];
  GstStructure *s;
  gint num_channels, i, p;

  s = gst_caps_get_structure (caps, 0);
  if (!gst_structure_get_int (s, "channels", &num_channels))
    g_return_val_if_reached (FALSE);

742
743
744
745
  /* In theory this should be done for 1 and 2 channels too but
   * apparently breaks too many things currently.
   */
  if (num_channels <= 2 || num_channels > MAX_CHANNEL_POSITIONS) {
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
    GST_DEBUG ("invalid number of channels: %d", num_channels);
    return FALSE;
  }

  p = 0;
  for (i = 0; i < MAX_CHANNEL_POSITIONS; ++i) {
    if ((layout & layout_mapping[i].ms_mask) != 0) {
      if (p >= num_channels) {
        GST_WARNING ("More bits set in the channel layout map than there "
            "are channels! Broken file");
        return FALSE;
      }
      if (layout_mapping[i].gst_pos == GST_AUDIO_CHANNEL_POSITION_INVALID) {
        GST_WARNING ("Unsupported channel position (mask 0x%08x) in channel "
            "layout map - ignoring those channels", layout_mapping[i].ms_mask);
        /* what to do? just ignore it and let downstream deal with a channel
         * layout that has INVALID positions in it for now ... */
      }
      pos[p] = layout_mapping[i].gst_pos;
      ++p;
    }
  }

  if (p != num_channels) {
    GST_WARNING ("Only %d bits set in the channel layout map, but there are "
        "supposed to be %d channels! Broken file", p, num_channels);
    return FALSE;
  }

  gst_audio_set_channel_positions (s, pos);
  return TRUE;
}

779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
static gboolean
gst_riff_wave_add_default_channel_layout (GstCaps * caps)
{
  GstAudioChannelPosition pos[8] = { GST_AUDIO_CHANNEL_POSITION_NONE, };
  GstStructure *s;
  gint nchannels;

  s = gst_caps_get_structure (caps, 0);

  if (!gst_structure_get_int (s, "channels", &nchannels))
    g_return_val_if_reached (FALSE);

  if (nchannels > 8) {
    GST_DEBUG ("invalid number of channels: %d", nchannels);
    return FALSE;
  }

  /* This uses the default channel mapping from ALSA which
   * is used in quite a few surround test files and seems to be
   * the defacto standard. The channel mapping from
   * WAVE_FORMAT_EXTENSIBLE doesn't seem to be used in normal
   * wav files like chan-id.wav.
   * http://bugzilla.gnome.org/show_bug.cgi?id=489010
   */
  switch (nchannels) {
    case 1:
      pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO;
      break;
    case 8:
      pos[7] = GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT;
      pos[6] = GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT;
      /* fall through */
    case 6:
      pos[5] = GST_AUDIO_CHANNEL_POSITION_LFE;
      /* fall through */
    case 5:
      pos[4] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
      /* fall through */
    case 4:
      pos[3] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
      pos[2] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
      /* fall through */
    case 2:
      pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
      pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
      break;
    default:
      return FALSE;
  }

  gst_audio_set_channel_positions (s, pos);
  return TRUE;
}

static guint32
gst_riff_wavext_get_default_channel_mask (guint nchannels)
{
  guint32 channel_mask = 0;

  /* Set the default channel mask for the given number of channels.
   * http://www.microsoft.com/whdc/device/audio/multichaud.mspx
   */
  switch (nchannels) {
    case 11:
      channel_mask |= 0x00400;
      channel_mask |= 0x00200;
    case 9:
      channel_mask |= 0x00100;
    case 8:
      channel_mask |= 0x00080;
      channel_mask |= 0x00040;
    case 6:
      channel_mask |= 0x00020;
      channel_mask |= 0x00010;
    case 4:
      channel_mask |= 0x00008;
    case 3:
      channel_mask |= 0x00004;
    case 2:
      channel_mask |= 0x00002;
      channel_mask |= 0x00001;
      break;
  }

  return channel_mask;
}

866
GstCaps *
867
gst_riff_create_audio_caps (guint16 codec_id,
868
869
    gst_riff_strh * strh, gst_riff_strf_auds * strf,
    GstBuffer * strf_data, GstBuffer * strd_data, char **codec_name)
870
{
871
  gboolean block_align = FALSE, rate_chan = TRUE;
872
  GstCaps *caps = NULL;
873
  gint rate_min = 1000, rate_max = 96000;
874
  gint channels_max = 2;
875
876

  switch (codec_id) {
877
    case GST_RIFF_WAVE_FORMAT_PCM:     /* PCM */
878
879
      channels_max = 8;

880
      if (strf != NULL) {
881
882
        gint ba = strf->blockalign;
        gint ch = strf->channels;
883
884
885
886
887
888
889
890
        gint wd, ws;

        /* If we have an empty blockalign, we take the width contained in 
         * strf->size */
        if (ba != 0)
          wd = ba * 8 / ch;
        else
          wd = strf->size;
891
892
893
894

        if (strf->size > 32) {
          GST_WARNING ("invalid depth (%d) of pcm audio, overwriting.",
              strf->size);
895
          strf->size = 8 * ((wd + 7) / 8);
896
        }
897

898
899
900
901
902
        /* in riff, the depth is stored in the size field but it just means that
         * the _least_ significant bits are cleared. We can therefore just play
         * the sample as if it had a depth == width */
        /* For reference, the actual depth is in strf->size */
        ws = wd;
903

904
905
906
        caps = gst_caps_new_simple ("audio/x-raw-int",
            "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
            "channels", G_TYPE_INT, ch,
907
908
            "width", G_TYPE_INT, wd,
            "depth", G_TYPE_INT, ws, "signed", G_TYPE_BOOLEAN, wd != 8, NULL);
909

910
911
912
913
        /* Add default channel layout. In theory this should be done
         * for 1 and 2 channels too but apparently breaks too many
         * things currently. Also we know no default layout for more than
         * 8 channels. */
914
        if (ch > 2) {
915
916
917
          if (ch > 8)
            GST_WARNING ("don't know default layout for %d channels", ch);
          else if (gst_riff_wave_add_default_channel_layout (caps))
918
            GST_DEBUG ("using default channel layout for %d channels", ch);
919
920
          else
            GST_WARNING ("failed to add channel layout");
921
        }
922
      } else {
923
        /* FIXME: this is pretty useless - we need fixed caps */
924
925
926
        caps = gst_caps_from_string ("audio/x-raw-int, "
            "endianness = (int) LITTLE_ENDIAN, "
            "signed = (boolean) { true, false }, "
927
            "width = (int) { 8, 16, 24, 32 }, " "depth = (int) [ 1, 32 ]");
928
      }
929
930
931
      if (codec_name && strf)
        *codec_name = g_strdup_printf ("Uncompressed %d-bit PCM audio",
            strf->size);
932
933
      break;

934
935
936
937
938
    case GST_RIFF_WAVE_FORMAT_ADPCM:
      caps = gst_caps_new_simple ("audio/x-adpcm",
          "layout", G_TYPE_STRING, "microsoft", NULL);
      if (codec_name)
        *codec_name = g_strdup ("ADPCM audio");
939
940
941
      block_align = TRUE;
      break;

942
    case GST_RIFF_WAVE_FORMAT_IEEE_FLOAT:
943
944
      channels_max = 8;

945
946
947
948
949
950
951
952
953
      if (strf != NULL) {
        gint ba = strf->blockalign;
        gint ch = strf->channels;
        gint wd = ba * 8 / ch;

        caps = gst_caps_new_simple ("audio/x-raw-float",
            "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
            "channels", G_TYPE_INT, ch, "width", G_TYPE_INT, wd, NULL);

954
955
956
957
        /* Add default channel layout. In theory this should be done
         * for 1 and 2 channels too but apparently breaks too many
         * things currently. Also we know no default layout for more than
         * 8 channels. */
958
        if (ch > 2) {
959
960
961
          if (ch > 8)
            GST_WARNING ("don't know default layout for %d channels", ch);
          else if (gst_riff_wave_add_default_channel_layout (caps))
962
            GST_DEBUG ("using default channel layout for %d channels", ch);
963
964
          else
            GST_WARNING ("failed to add channel layout");
965
966
967
968
969
970
971
972
973
974
975
        }
      } else {
        /* FIXME: this is pretty useless - we need fixed caps */
        caps = gst_caps_from_string ("audio/x-raw-float, "
            "endianness = (int) LITTLE_ENDIAN, " "width = (int) { 32, 64 }");
      }
      if (codec_name && strf)
        *codec_name = g_strdup_printf ("Uncompressed %d-bit IEEE float audio",
            strf->size);
      break;

976
977
978
979
980
981
982
983
984
    case GST_RIFF_WAVE_FORMAT_IBM_CVSD:
      goto unknown;

    case GST_RIFF_WAVE_FORMAT_ALAW:
      if (strf != NULL) {
        if (strf->size != 8) {
          GST_WARNING ("invalid depth (%d) of alaw audio, overwriting.",
              strf->size);
          strf->size = 8;
985
986
          strf->blockalign = (strf->size * strf->channels) / 8;
          strf->av_bps = strf->blockalign * strf->rate;
987
988
989
990
        }
        if (strf->av_bps == 0 || strf->blockalign == 0) {
          GST_WARNING ("fixing av_bps (%d) and blockalign (%d) of alaw audio",
              strf->av_bps, strf->blockalign);
991
992
          strf->blockalign = (strf->size * strf->channels) / 8;
          strf->av_bps = strf->blockalign * strf->rate;
993
994
        }
      }
995
      rate_max = 48000;
996
997
998
999
1000
      caps = gst_caps_new_simple ("audio/x-alaw", NULL);
      if (codec_name)
        *codec_name = g_strdup ("A-law audio");
      break;

1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
    case GST_RIFF_WAVE_FORMAT_WMS:
      caps = gst_caps_new_simple ("audio/x-wms", NULL);
      if (strf != NULL) {
        gst_caps_set_simple (caps,
            "bitrate", G_TYPE_INT, strf->av_bps * 8,
            "width", G_TYPE_INT, strf->size,
            "depth", G_TYPE_INT, strf->size, NULL);
      } else {
        gst_caps_set_simple (caps,
            "bitrate", GST_TYPE_INT_RANGE, 0, G_MAXINT, NULL);
      }
      if (codec_name)
        *codec_name = g_strdup ("Windows Media Audio Speech");
      block_align = TRUE;
      break;

1017
1018
1019
1020
1021
1022
    case GST_RIFF_WAVE_FORMAT_MULAW:
      if (strf != NULL) {
        if (strf->size != 8) {
          GST_WARNING ("invalid depth (%d) of mulaw audio, overwriting.",
              strf->size);
          strf->size = 8;
1023
1024
          strf->blockalign = (strf->size * strf->channels) / 8;
          strf->av_bps = strf->blockalign * strf->rate;
1025
1026
1027
1028
        }
        if (strf->av_bps == 0 || strf->blockalign == 0) {
          GST_WARNING ("fixing av_bps (%d) and blockalign (%d) of mulaw audio",
              strf->av_bps, strf->blockalign);
1029
1030
          strf->blockalign = (strf->size * strf->channels) / 8;
          strf->av_bps = strf->blockalign * strf->rate;
1031
1032
        }
      }
1033
      rate_max = 48000;
1034
1035
1036
1037
1038
1039
1040
1041
      caps = gst_caps_new_simple ("audio/x-mulaw", NULL);
      if (codec_name)
        *codec_name = g_strdup ("Mu-law audio");
      break;

    case GST_RIFF_WAVE_FORMAT_OKI_ADPCM:
      goto unknown;

1042
    case GST_RIFF_WAVE_FORMAT_DVI_ADPCM:
1043
      rate_max = 48000;
1044
1045
1046
1047
1048
      caps = gst_caps_new_simple ("audio/x-adpcm",
          "layout", G_TYPE_STRING, "dvi", NULL);
      if (codec_name)
        *codec_name = g_strdup ("DVI ADPCM audio");
      block_align = TRUE;
1049
1050
      break;

1051
1052
1053
    case GST_RIFF_WAVE_FORMAT_DSP_TRUESPEECH:
      rate_min = 8000;
      rate_max = 8000;
1054
      caps = gst_caps_new_simple ("audio/x-truespeech", NULL);
1055
1056
1057
1058
      if (codec_name)
        *codec_name = g_strdup ("DSP Group TrueSpeech");
      break;

1059
1060
    case GST_RIFF_WAVE_FORMAT_GSM610:
    case GST_RIFF_WAVE_FORMAT_MSN:
1061
      rate_min = 1;
1062
      caps = gst_caps_new_simple ("audio/ms-gsm", NULL);
1063
      if (codec_name)
1064
        *codec_name = g_strdup ("MS GSM audio");
1065
1066
      break;

1067
    case GST_RIFF_WAVE_FORMAT_MPEGL12: /* mp1 or mp2 */
1068
1069
      rate_min = 16000;
      rate_max = 48000;
1070
1071
      caps = gst_caps_new_simple ("audio/mpeg",
          "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 2, NULL);
1072
      if (codec_name)
1073
1074
1075
1076
        *codec_name = g_strdup ("MPEG-1 layer 2");
      break;

    case GST_RIFF_WAVE_FORMAT_MPEGL3:  /* mp3 */
1077
      rate_min = 8000;
1078
      rate_max = 48000;
1079
1080
1081
1082
      caps = gst_caps_new_simple ("audio/mpeg",
          "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 3, NULL);
      if (codec_name)
        *codec_name = g_strdup ("MPEG-1 layer 3");
1083
1084
      break;

1085
1086
1087
1088
1089
1090
    case GST_RIFF_WAVE_FORMAT_VORBIS1: /* ogg/vorbis mode 1 */
    case GST_RIFF_WAVE_FORMAT_VORBIS2: /* ogg/vorbis mode 2 */
    case GST_RIFF_WAVE_FORMAT_VORBIS3: /* ogg/vorbis mode 3 */
    case GST_RIFF_WAVE_FORMAT_VORBIS1PLUS:     /* ogg/vorbis mode 1+ */
    case GST_RIFF_WAVE_FORMAT_VORBIS2PLUS:     /* ogg/vorbis mode 2+ */
    case GST_RIFF_WAVE_FORMAT_VORBIS3PLUS:     /* ogg/vorbis mode 3+ */
David Schleef's avatar
David Schleef committed
1091
      caps = gst_caps_new_simple ("audio/x-vorbis", NULL);
1092
      if (codec_name)
1093
        *codec_name = g_strdup ("Vorbis");
1094
1095
1096
      break;

    case GST_RIFF_WAVE_FORMAT_A52:
1097
      channels_max = 6;
David Schleef's avatar
David Schleef committed
1098
      caps = gst_caps_new_simple ("audio/x-ac3", NULL);
1099
      if (codec_name)
1100
        *codec_name = g_strdup ("AC-3 audio");
1101
      break;
1102
1103
1104
1105
1106
    case GST_RIFF_WAVE_FORMAT_DTS:
      channels_max = 6;
      caps = gst_caps_new_simple ("audio/x-dts", NULL);
      if (codec_name)
        *codec_name = g_strdup ("DTS audio");
1107
1108
      /* wavparse is not always able to specify rate/channels for DTS-in-wav */
      rate_chan = FALSE;
1109
      break;
1110
1111
1112
1113
1114
1115
1116
1117
1118
    case GST_RIFF_WAVE_FORMAT_AAC:
    {
      channels_max = 8;
      caps = gst_caps_new_simple ("audio/mpeg",
          "mpegversion", G_TYPE_INT, 4, NULL);
      if (codec_name)
        *codec_name = g_strdup ("MPEG-4 AAC audio");
      break;
    }
1119
1120
    case GST_RIFF_WAVE_FORMAT_WMAV1:
    case GST_RIFF_WAVE_FORMAT_WMAV2:
1121
    case GST_RIFF_WAVE_FORMAT_WMAV3:
1122
    {
1123
      gint version = (codec_id - GST_RIFF_WAVE_FORMAT_WMAV1) + 1;
1124

1125
      channels_max = 6;
1126
1127
1128
1129
1130
1131
      block_align = TRUE;

      caps = gst_caps_new_simple ("audio/x-wma",
          "wmaversion", G_TYPE_INT, version, NULL);

      if (codec_name)
1132
        *codec_name = g_strdup_printf ("WMA Version %d", version + 6);
1133

1134
1135
      if (strf != NULL) {
        gst_caps_set_simple (caps,
Fabrizio's avatar
Fabrizio committed
1136
1137
            "bitrate", G_TYPE_INT, strf->av_bps * 8,
            "depth", G_TYPE_INT, strf->size, NULL);