riff-media.c 61.7 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
    case GST_MAKE_FOURCC ('D', 'I', 'B', ' '): /* uncompressed RGB */
    case GST_MAKE_FOURCC (0x00, 0x00, 0x00, 0x00):
    case GST_MAKE_FOURCC ('R', 'G', 'B', ' '):
    case GST_MAKE_FOURCC ('R', 'A', 'W', ' '):
    {
67 68 69 70 71 72 73 74 75 76 77 78 79
      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);
80 81 82 83 84 85
        } else if (bpp == 32) {
          caps = gst_caps_new_simple ("video/x-raw-rgb",
              "bpp", G_TYPE_INT, 32, "depth", G_TYPE_INT, 24,
              "endianness", G_TYPE_INT, G_BIG_ENDIAN,
              "red_mask", G_TYPE_INT, 0xff00, "green_mask", G_TYPE_INT,
              0xff0000, "blue_mask", G_TYPE_INT, 0xff000000, NULL);
86 87
        } else {
          GST_WARNING ("Unhandled DIB RGB depth: %d", bpp);
88
          return NULL;
89 90 91
        }
      } else {
        /* for template */
92 93
        caps =
            gst_caps_from_string ("video/x-raw-rgb, bpp = (int) { 8, 24, 32 }, "
94 95 96
            "depth = (int) { 8, 24}");
      }

97 98
      palette = strf_data;
      strf_data = NULL;
99 100 101 102 103 104
      if (codec_name) {
        if (bpp == 8)
          *codec_name = g_strdup_printf ("Palettized %d-bit RGB", bpp);
        else
          *codec_name = g_strdup_printf ("%d-bit RGB", bpp);
      }
105
      break;
106
    }
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
107
    case GST_MAKE_FOURCC ('I', '4', '2', '0'):
108
      caps = gst_caps_new_simple ("video/x-raw-yuv",
109
          "format", GST_TYPE_FOURCC, codec_fcc, NULL);
110
      if (codec_name)
111
        *codec_name = g_strdup ("Uncompressed planar YUV 4:2:0");
112
      break;
113

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
114
    case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
David Schleef's avatar
David Schleef committed
115
      caps = gst_caps_new_simple ("video/x-raw-yuv",
116
          "format", GST_TYPE_FOURCC, codec_fcc, NULL);
117
      if (codec_name)
118
        *codec_name = g_strdup ("Uncompressed packed YUV 4:2:2");
119 120
      break;

121 122 123 124 125 126 127
    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;

128 129 130 131 132 133 134
    case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
      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 YUV 4:2:2");
      break;

135 136 137 138 139 140 141
    case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
      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:2:2");
      break;

142
    case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'): /* YUY2 MJPEG */
143 144 145
    case GST_MAKE_FOURCC ('A', 'V', 'R', 'n'):
    case GST_MAKE_FOURCC ('I', 'J', 'P', 'G'):
    case GST_MAKE_FOURCC ('i', 'j', 'p', 'g'):
Edward Hervey's avatar
Edward Hervey committed
146 147 148
    case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
    case GST_MAKE_FOURCC ('A', 'C', 'D', 'V'):
    case GST_MAKE_FOURCC ('Q', 'I', 'V', 'G'):
149
      caps = gst_caps_new_simple ("image/jpeg", NULL);
150
      if (codec_name)
151
        *codec_name = g_strdup ("Motion JPEG");
152
      break;
153

154
    case GST_MAKE_FOURCC ('J', 'P', 'E', 'G'): /* generic (mostly RGB) MJPEG */
155
    case GST_MAKE_FOURCC ('j', 'p', 'e', 'g'): /* generic (mostly RGB) MJPEG */
156
      caps = gst_caps_new_simple ("image/jpeg", NULL);
157
      if (codec_name)
158
        *codec_name = g_strdup ("JPEG Still Image");
159
      break;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
160

161 162
    case GST_MAKE_FOURCC ('P', 'I', 'X', 'L'): /* Miro/Pinnacle fourccs */
    case GST_MAKE_FOURCC ('V', 'I', 'X', 'L'): /* Miro/Pinnacle fourccs */
163
      caps = gst_caps_new_simple ("image/jpeg", NULL);
164
      if (codec_name)
Edward Hervey's avatar
Edward Hervey committed
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
        *codec_name = g_strdup ("Miro/Pinnacle Motion JPEG");
      break;

    case GST_MAKE_FOURCC ('C', 'J', 'P', 'G'):
      caps = gst_caps_new_simple ("image/jpeg", NULL);
      if (codec_name)
        *codec_name = g_strdup ("Creative Webcam JPEG");
      break;

    case GST_MAKE_FOURCC ('S', 'L', 'M', 'J'):
      caps = gst_caps_new_simple ("image/jpeg", NULL);
      if (codec_name)
        *codec_name = g_strdup ("SL Motion JPEG");
      break;

    case GST_MAKE_FOURCC ('J', 'P', 'G', 'L'):
      caps = gst_caps_new_simple ("image/jpeg", NULL);
      if (codec_name)
        *codec_name = g_strdup ("Pegasus Lossless JPEG");
184
      break;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
185

186 187 188 189 190 191 192 193 194 195 196
    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
197 198
    case GST_MAKE_FOURCC ('H', 'F', 'Y', 'U'):
      caps = gst_caps_new_simple ("video/x-huffyuv", NULL);
199 200 201 202
      if (strf) {
        gst_caps_set_simple (caps, "bpp",
            G_TYPE_INT, (int) strf->bit_cnt, NULL);
      }
203
      if (codec_name)
204
        *codec_name = g_strdup ("Huffman Lossless Codec");
205
      break;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
206 207 208

    case GST_MAKE_FOURCC ('M', 'P', 'E', 'G'):
    case GST_MAKE_FOURCC ('M', 'P', 'G', 'I'):
209 210
    case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
    case GST_MAKE_FOURCC ('M', 'P', 'G', '1'):
211
    case GST_MAKE_FOURCC ('P', 'I', 'M', '1'):
212
    case GST_MAKE_FOURCC (0x01, 0x00, 0x00, 0x10):
David Schleef's avatar
David Schleef committed
213
      caps = gst_caps_new_simple ("video/mpeg",
214
          "systemstream", G_TYPE_BOOLEAN, FALSE,
215
          "mpegversion", G_TYPE_INT, 1, NULL);
216
      if (codec_name)
217
        *codec_name = g_strdup ("MPEG-1 video");
218
      break;
Edward Hervey's avatar
Edward Hervey committed
219

220 221
    case GST_MAKE_FOURCC ('M', 'P', 'G', '2'):
    case GST_MAKE_FOURCC ('m', 'p', 'g', '2'):
Edward Hervey's avatar
Edward Hervey committed
222
    case GST_MAKE_FOURCC ('P', 'I', 'M', '2'):
223
    case GST_MAKE_FOURCC ('D', 'V', 'R', ' '):
224
    case GST_MAKE_FOURCC (0x02, 0x00, 0x00, 0x10):
225 226 227 228
      caps = gst_caps_new_simple ("video/mpeg",
          "systemstream", G_TYPE_BOOLEAN, FALSE,
          "mpegversion", G_TYPE_INT, 2, NULL);
      if (codec_name)
229
        *codec_name = g_strdup ("MPEG-2 video");
230
      break;
231

Edward Hervey's avatar
Edward Hervey committed
232 233 234 235 236 237 238 239
    case GST_MAKE_FOURCC ('L', 'M', 'P', '2'):
      caps = gst_caps_new_simple ("video/mpeg",
          "systemstream", G_TYPE_BOOLEAN, FALSE,
          "mpegversion", G_TYPE_INT, 2, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Lead MPEG-2 video");
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
240
    case GST_MAKE_FOURCC ('H', '2', '6', '3'):
241
    case GST_MAKE_FOURCC ('h', '2', '6', '3'):
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
242
    case GST_MAKE_FOURCC ('i', '2', '6', '3'):
243
    case GST_MAKE_FOURCC ('U', '2', '6', '3'):
Edward Hervey's avatar
Edward Hervey committed
244 245
    case GST_MAKE_FOURCC ('v', 'i', 'v', '1'):
    case GST_MAKE_FOURCC ('T', '2', '6', '3'):
246 247
      caps = gst_caps_new_simple ("video/x-h263",
          "variant", G_TYPE_STRING, "itu", NULL);
248
      if (codec_name)
249
        *codec_name = g_strdup ("ITU H.26n");
250
      break;
251

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
252
    case GST_MAKE_FOURCC ('L', '2', '6', '3'):
253 254 255
      /* http://www.leadcodecs.com/Codecs/LEAD-H263.htm */
      caps = gst_caps_new_simple ("video/x-h263",
          "variant", G_TYPE_STRING, "lead", NULL);
256
      if (codec_name)
257
        *codec_name = g_strdup ("Lead H.263");
258
      break;
259

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
260
    case GST_MAKE_FOURCC ('M', '2', '6', '3'):
261
    case GST_MAKE_FOURCC ('m', '2', '6', '3'):
262 263
      caps = gst_caps_new_simple ("video/x-h263",
          "variant", G_TYPE_STRING, "microsoft", NULL);
264
      if (codec_name)
265
        *codec_name = g_strdup ("Microsoft H.263");
266
      break;
267

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
268
    case GST_MAKE_FOURCC ('V', 'D', 'O', 'W'):
269 270
      caps = gst_caps_new_simple ("video/x-h263",
          "variant", G_TYPE_STRING, "vdolive", NULL);
271
      if (codec_name)
272
        *codec_name = g_strdup ("VDOLive");
273
      break;
274

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
275
    case GST_MAKE_FOURCC ('V', 'I', 'V', 'O'):
276 277
      caps = gst_caps_new_simple ("video/x-h263",
          "variant", G_TYPE_STRING, "vivo", NULL);
278
      if (codec_name)
279
        *codec_name = g_strdup ("Vivo H.263");
280
      break;
281

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
282
    case GST_MAKE_FOURCC ('x', '2', '6', '3'):
283 284
      caps = gst_caps_new_simple ("video/x-h263",
          "variant", G_TYPE_STRING, "xirlink", NULL);
285
      if (codec_name)
286
        *codec_name = g_strdup ("Xirlink H.263");
287 288
      break;

289 290
      /* apparently not standard H.263...? */
    case GST_MAKE_FOURCC ('I', '2', '6', '3'):
291 292
      caps = gst_caps_new_simple ("video/x-intel-h263",
          "variant", G_TYPE_STRING, "intel", NULL);
293 294 295 296
      if (codec_name)
        *codec_name = g_strdup ("Intel H.263");
      break;

Edward Hervey's avatar
Edward Hervey committed
297 298 299 300 301 302 303
    case GST_MAKE_FOURCC ('V', 'X', '1', 'K'):
      caps = gst_caps_new_simple ("video/x-h263",
          "variant", G_TYPE_STRING, "lucent", NULL);
      if (codec_name)
        *codec_name = g_strdup ("Lucent VX1000S H.263");
      break;

304 305
    case GST_MAKE_FOURCC ('X', '2', '6', '4'):
    case GST_MAKE_FOURCC ('x', '2', '6', '4'):
306
    case GST_MAKE_FOURCC ('H', '2', '6', '4'):
307
    case GST_MAKE_FOURCC ('h', '2', '6', '4'):
308 309
    case GST_MAKE_FOURCC ('a', 'v', 'c', '1'):
    case GST_MAKE_FOURCC ('A', 'V', 'C', '1'):
310 311
      caps = gst_caps_new_simple ("video/x-h264",
          "variant", G_TYPE_STRING, "itu", NULL);
312 313 314 315 316
      if (codec_name)
        *codec_name = g_strdup ("ITU H.264");
      break;

    case GST_MAKE_FOURCC ('V', 'S', 'S', 'H'):
317 318
      caps = gst_caps_new_simple ("video/x-h264",
          "variant", G_TYPE_STRING, "videosoft", NULL);
319 320 321 322
      if (codec_name)
        *codec_name = g_strdup ("VideoSoft H.264");
      break;

323 324 325 326 327 328 329 330
    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;

331 332 333 334 335 336 337
    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;

Edward Hervey's avatar
Edward Hervey committed
338 339 340 341 342 343 344
    case GST_MAKE_FOURCC ('M', '4', 'C', 'C'):
      caps = gst_caps_new_simple ("video/mpeg",
          "mpegversion", G_TYPE_INT, 4, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Divio MPEG-4");
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
345
    case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
346
    case GST_MAKE_FOURCC ('d', 'i', 'v', '3'):
Edward Hervey's avatar
Edward Hervey committed
347 348
    case GST_MAKE_FOURCC ('D', 'V', 'X', '3'):
    case GST_MAKE_FOURCC ('d', 'v', 'x', '3'):
349
    case GST_MAKE_FOURCC ('D', 'I', 'V', '4'):
350
    case GST_MAKE_FOURCC ('d', 'i', 'v', '4'):
351
    case GST_MAKE_FOURCC ('D', 'I', 'V', '5'):
352
    case GST_MAKE_FOURCC ('d', 'i', 'v', '5'):
353
    case GST_MAKE_FOURCC ('D', 'I', 'V', '6'):
354
    case GST_MAKE_FOURCC ('d', 'i', 'v', '6'):
355 356 357 358 359 360 361
    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
362
      caps = gst_caps_new_simple ("video/x-divx",
363
          "divxversion", G_TYPE_INT, 3, NULL);
364
      if (codec_name)
365
        *codec_name = g_strdup ("DivX MS-MPEG-4 Version 3");
366
      break;
367

368 369
    case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
    case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
370
      caps = gst_caps_new_simple ("video/x-divx",
371
          "divxversion", G_TYPE_INT, 4, NULL);
372
      if (codec_name)
373
        *codec_name = g_strdup ("DivX MPEG-4 Version 4");
374
      break;
375

376 377 378 379 380 381 382
    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
383
    case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
David Schleef's avatar
David Schleef committed
384
      caps = gst_caps_new_simple ("video/x-divx",
385
          "divxversion", G_TYPE_INT, 5, NULL);
386
      if (codec_name)
387
        *codec_name = g_strdup ("DivX MPEG-4 Version 5");
388 389
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
390 391
    case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
    case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
David Schleef's avatar
David Schleef committed
392
      caps = gst_caps_new_simple ("video/x-xvid", NULL);
393
      if (codec_name)
394
        *codec_name = g_strdup ("XVID MPEG-4");
395 396
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
397
    case GST_MAKE_FOURCC ('M', 'P', 'G', '4'):
Edward Hervey's avatar
Edward Hervey committed
398 399
    case GST_MAKE_FOURCC ('M', 'P', '4', '1'):
    case GST_MAKE_FOURCC ('m', 'p', '4', '1'):
David Schleef's avatar
David Schleef committed
400
      caps = gst_caps_new_simple ("video/x-msmpeg",
401
          "msmpegversion", G_TYPE_INT, 41, NULL);
402
      if (codec_name)
403
        *codec_name = g_strdup ("Microsoft MPEG-4 4.1");
404 405
      break;

406
    case GST_MAKE_FOURCC ('m', 'p', '4', '2'):
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
407
    case GST_MAKE_FOURCC ('M', 'P', '4', '2'):
David Schleef's avatar
David Schleef committed
408
      caps = gst_caps_new_simple ("video/x-msmpeg",
409
          "msmpegversion", G_TYPE_INT, 42, NULL);
410
      if (codec_name)
411
        *codec_name = g_strdup ("Microsoft MPEG-4 4.2");
412 413
      break;

414
    case GST_MAKE_FOURCC ('m', 'p', '4', '3'):
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
415
    case GST_MAKE_FOURCC ('M', 'P', '4', '3'):
David Schleef's avatar
David Schleef committed
416
      caps = gst_caps_new_simple ("video/x-msmpeg",
417
          "msmpegversion", G_TYPE_INT, 43, NULL);
418
      if (codec_name)
419
        *codec_name = g_strdup ("Microsoft MPEG-4 4.3");
420 421
      break;

422
    case GST_MAKE_FOURCC ('M', 'P', '4', 'S'):
423 424 425 426 427 428 429 430
    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'):
431
    case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
Edward Hervey's avatar
Edward Hervey committed
432
    case GST_MAKE_FOURCC ('F', 'F', 'D', 'S'):
433 434 435 436 437 438
      caps = gst_caps_new_simple ("video/mpeg",
          "mpegversion", G_TYPE_INT, 4, NULL);
      if (codec_name)
        *codec_name = g_strdup ("FFmpeg MPEG-4");
      break;

Edward Hervey's avatar
Edward Hervey committed
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
    case GST_MAKE_FOURCC ('E', 'M', '4', 'A'):
    case GST_MAKE_FOURCC ('E', 'P', 'V', 'H'):
    case GST_MAKE_FOURCC ('F', 'V', 'F', 'W'):
    case GST_MAKE_FOURCC ('I', 'N', 'M', 'C'):
    case GST_MAKE_FOURCC ('D', 'I', 'G', 'I'):
    case GST_MAKE_FOURCC ('D', 'M', '2', 'K'):
    case GST_MAKE_FOURCC ('D', 'C', 'O', 'D'):
    case GST_MAKE_FOURCC ('M', 'V', 'X', 'M'):
    case GST_MAKE_FOURCC ('P', 'M', '4', 'V'):
    case GST_MAKE_FOURCC ('S', 'M', 'P', '4'):
    case GST_MAKE_FOURCC ('D', 'X', 'G', 'M'):
    case GST_MAKE_FOURCC ('V', 'I', 'D', 'M'):
    case GST_MAKE_FOURCC ('M', '4', 'T', '3'):
    case GST_MAKE_FOURCC ('G', 'E', 'O', 'X'):
      caps = gst_caps_new_simple ("video/mpeg",
          "mpegversion", G_TYPE_INT, 4, NULL);
      if (codec_name)
        *codec_name = g_strdup ("MPEG-4");
      break;

459 460
    case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
    case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
461 462
      caps = gst_caps_new_simple ("video/x-msmpeg",
          "msmpegversion", G_TYPE_INT, 43, NULL);
463 464
      if (codec_name)
        *codec_name = g_strdup ("Microsoft MPEG-4 4.3");        /* FIXME? */
465
      break;
466

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
467 468 469
    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);
470
      if (codec_name)
471
        *codec_name = g_strdup ("3ivx");
472 473
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
474 475
    case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
    case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
Edward Hervey's avatar
Edward Hervey committed
476 477
    case GST_MAKE_FOURCC ('d', 'v', 'c', ' '):
    case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
David Schleef's avatar
David Schleef committed
478
      caps = gst_caps_new_simple ("video/x-dv",
479 480
          "systemstream", G_TYPE_BOOLEAN, FALSE,
          "dvversion", G_TYPE_INT, 25, NULL);
481
      if (codec_name)
482
        *codec_name = g_strdup ("Generic DV");
483 484
      break;

Edward Hervey's avatar
Edward Hervey committed
485 486 487 488 489 490 491 492 493
    case GST_MAKE_FOURCC ('C', 'D', 'V', 'C'):
    case GST_MAKE_FOURCC ('c', 'd', 'v', 'c'):
      caps = gst_caps_new_simple ("video/x-dv",
          "systemstream", G_TYPE_BOOLEAN, FALSE,
          "dvversion", G_TYPE_INT, 25, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Canopus DV");
      break;

494 495 496 497 498 499 500 501 502
    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
503
    case GST_MAKE_FOURCC ('W', 'M', 'V', '1'):
David Schleef's avatar
David Schleef committed
504
      caps = gst_caps_new_simple ("video/x-wmv",
505
          "wmvversion", G_TYPE_INT, 1, NULL);
506
      if (codec_name)
507
        *codec_name = g_strdup ("Microsoft Windows Media 7");
508 509
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
510
    case GST_MAKE_FOURCC ('W', 'M', 'V', '2'):
David Schleef's avatar
David Schleef committed
511
      caps = gst_caps_new_simple ("video/x-wmv",
512
          "wmvversion", G_TYPE_INT, 2, NULL);
513
      if (codec_name)
514
        *codec_name = g_strdup ("Microsoft Windows Media 8");
515
      break;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
516 517

    case GST_MAKE_FOURCC ('W', 'M', 'V', '3'):
518
      caps = gst_caps_new_simple ("video/x-wmv",
519
          "wmvversion", G_TYPE_INT, 3, NULL);
520
      if (codec_name)
521
        *codec_name = g_strdup ("Microsoft Windows Media 9");
522 523
      break;

524 525
    case GST_MAKE_FOURCC ('W', 'M', 'V', 'A'):
      caps = gst_caps_new_simple ("video/x-wmv",
526
          "wmvversion", G_TYPE_INT, 3, "format", GST_TYPE_FOURCC,
527 528 529 530 531
          codec_fcc, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Microsoft Windows Media Advanced Profile");
      break;

532 533
    case GST_MAKE_FOURCC ('W', 'V', 'C', '1'):
      caps = gst_caps_new_simple ("video/x-wmv",
534
          "wmvversion", G_TYPE_INT, 3, "format", GST_TYPE_FOURCC,
535 536 537 538 539
          codec_fcc, NULL);
      if (codec_name)
        *codec_name = g_strdup ("Microsoft Windows Media VC-1");
      break;

540 541 542 543 544 545
    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;

546 547 548 549 550 551 552 553 554 555
    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");
556 557
      palette = strf_data;
      strf_data = NULL;
558 559
      break;

560 561 562
    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? */
Edward Hervey's avatar
Edward Hervey committed
563
    case GST_MAKE_FOURCC (0x2, 0x0, 0x0, 0x0): /* why, why, why? */
564 565
      caps = gst_caps_new_simple ("video/x-rle",
          "layout", G_TYPE_STRING, "microsoft", NULL);
566 567
      palette = strf_data;
      strf_data = NULL;
568 569 570 571 572 573 574
      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)
575 576 577
        *codec_name = g_strdup ("Microsoft RLE");
      break;

578 579 580 581 582 583
    case GST_MAKE_FOURCC ('A', 'A', 'S', 'C'):
      caps = gst_caps_new_simple ("video/x-aasc", NULL);
      if (codec_name)
        *codec_name = g_strdup ("Autodesk Animator");
      break;

584 585 586 587 588
    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");
589 590
      break;

591 592 593 594 595 596 597 598
    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'):
599
    case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
600 601
    case GST_MAKE_FOURCC ('i', 'v', '3', '1'):
    case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
602 603 604 605 606 607
      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;

608 609 610 611 612 613 614 615
    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;

616
    case GST_MAKE_FOURCC ('I', 'V', '5', '0'):
617 618
      caps = gst_caps_new_simple ("video/x-indeo",
          "indeoversion", G_TYPE_INT, 5, NULL);
619 620 621 622
      if (codec_name)
        *codec_name = g_strdup ("Intel Video 5");
      break;

623 624 625 626 627 628 629 630 631 632 633 634 635
    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'):
Edward Hervey's avatar
Edward Hervey committed
636
    case GST_MAKE_FOURCC ('c', 'l', 'j', 'r'):
637 638 639 640 641 642 643 644 645 646 647 648 649
      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'):
Edward Hervey's avatar
Edward Hervey committed
650
    case GST_MAKE_FOURCC ('P', 'V', 'E', 'Z'):
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
      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'):
681 682
    case GST_MAKE_FOURCC ('t', 's', 'c', 'c'):{
      if (strf) {
683
        gint depth = (strf->bit_cnt != 0) ? (gint) strf->bit_cnt : 24;
684

685 686
        caps = gst_caps_new_simple ("video/x-camtasia", "depth", G_TYPE_INT,
            depth, NULL);
687 688 689 690
      } else {
        /* template caps */
        caps = gst_caps_new_simple ("video/x-camtasia", NULL);
      }
691 692 693
      if (codec_name)
        *codec_name = g_strdup ("TechSmith Camtasia");
      break;
694
    }
695 696 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

    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;

732 733 734 735 736 737 738
    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;

739 740 741 742 743 744 745
    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;

746 747 748 749 750 751
    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;

Edward Hervey's avatar
Edward Hervey committed
752 753 754 755 756 757 758 759 760
    case GST_RIFF_rpza:
    case GST_RIFF_azpr:
    case GST_MAKE_FOURCC ('R', 'P', 'Z', 'A'):
      caps = gst_caps_new_simple ("video/x-apple-video", NULL);
      if (codec_name)
        *codec_name = g_strdup ("Apple Video (RPZA)");
      break;


761 762 763 764 765 766 767
    case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
      caps = gst_caps_new_simple ("video/x-ffv",
          "ffvversion", G_TYPE_INT, 1, NULL);
      if (codec_name)
        *codec_name = g_strdup ("FFmpeg lossless video codec");
      break;

768 769 770 771 772 773
    case GST_MAKE_FOURCC ('K', 'M', 'V', 'C'):
      caps = gst_caps_new_simple ("video/x-kmvc", NULL);
      if (codec_name)
        *codec_name = g_strdup ("Karl Morton's video codec");
      break;

774 775 776 777 778 779 780
    case GST_MAKE_FOURCC ('v', 'p', '6', '0'):
    case GST_MAKE_FOURCC ('V', 'P', '6', '0'):
      caps = gst_caps_new_simple ("video/x-vp6", NULL);
      if (codec_name)
        *codec_name = g_strdup ("On2 VP6");
      break;

Edward Hervey's avatar
Edward Hervey committed
781 782 783 784 785 786
    case GST_MAKE_FOURCC ('L', 'M', '2', '0'):
      caps = gst_caps_new_simple ("video/x-mimic", NULL);
      if (codec_name)
        *codec_name = g_strdup ("Mimic webcam");
      break;

Wim Taymans's avatar
Wim Taymans committed
787 788 789 790 791 792 793
    case GST_MAKE_FOURCC ('T', 'H', 'E', 'O'):
    case GST_MAKE_FOURCC ('t', 'h', 'e', 'o'):
      caps = gst_caps_new_simple ("video/x-theora", NULL);
      if (codec_name)
        *codec_name = g_strdup ("Theora video codec");

      break;
Edward Hervey's avatar
Edward Hervey committed
794

795 796 797 798 799 800 801
    case GST_MAKE_FOURCC ('F', 'P', 'S', '1'):
      caps = gst_caps_new_simple ("video/x-fraps", NULL);
      if (codec_name)
        *codec_name = g_strdup ("Fraps video");

      break;

802
    default:
803
      GST_WARNING ("Unknown video fourcc %" GST_FOURCC_FORMAT,
804
          GST_FOURCC_ARGS (codec_fcc));
David Schleef's avatar
David Schleef committed
805
      return NULL;
806 807
  }

David Schleef's avatar
David Schleef committed
808
  if (strh != NULL) {
809 810
    gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
        strh->rate, strh->scale, NULL);
David Schleef's avatar
David Schleef committed
811 812
  } else {
    gst_caps_set_simple (caps,
813
        "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
David Schleef's avatar
David Schleef committed
814 815 816 817
  }

  if (strf != NULL) {
    gst_caps_set_simple (caps,
818 819
        "width", G_TYPE_INT, strf->width,
        "height", G_TYPE_INT, strf->height, NULL);
David Schleef's avatar
David Schleef committed
820 821
  } else {
    gst_caps_set_simple (caps,
822 823
        "width", GST_TYPE_INT_RANGE, 16, 4096,
        "height", GST_TYPE_INT_RANGE, 16, 4096, NULL);
824 825
  }

826 827
  /* extradata */
  if (strf_data || strd_data) {
Wim Taymans's avatar
Wim Taymans committed
828 829 830 831 832
    GstBuffer *codec_data;

    codec_data = strf_data ? strf_data : strd_data;

    gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_data, NULL);
833 834
  }

835
  /* palette */
836 837 838 839 840 841 842 843 844
  if (palette) {
    GstBuffer *copy;
    guint num_colors;

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

845 846
    if (GST_BUFFER_SIZE (palette) >= (num_colors * 4)) {
      /* palette is always at least 256*4 bytes */
847 848
      copy =
          gst_buffer_new_and_alloc (MAX (GST_BUFFER_SIZE (palette), 256 * 4));
849 850
      memcpy (GST_BUFFER_DATA (copy), GST_BUFFER_DATA (palette),
          GST_BUFFER_SIZE (palette));
851 852

#if (G_BYTE_ORDER == G_BIG_ENDIAN)
853 854 855 856 857 858 859 860 861 862
      {
        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);
        }
      }
863
#endif
864 865 866 867 868
      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");
    }
869 870
  }

871 872 873
  return caps;
}

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 913 914 915 916 917 918
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);

919 920 921 922
  /* 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) {
923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955
    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 (