riff-media.c 61.4 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
    case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'): /* YUY2 MJPEG */
136 137 138
    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
139 140 141
    case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
    case GST_MAKE_FOURCC ('A', 'C', 'D', 'V'):
    case GST_MAKE_FOURCC ('Q', 'I', 'V', 'G'):
142
      caps = gst_caps_new_simple ("image/jpeg", NULL);
143
      if (codec_name)
144
        *codec_name = g_strdup ("Motion JPEG");
145
      break;
146

147
    case GST_MAKE_FOURCC ('J', 'P', 'E', 'G'): /* generic (mostly RGB) MJPEG */
148
    case GST_MAKE_FOURCC ('j', 'p', 'e', 'g'): /* generic (mostly RGB) MJPEG */
149
      caps = gst_caps_new_simple ("image/jpeg", NULL);
150
      if (codec_name)
151
        *codec_name = g_strdup ("JPEG Still Image");
152
      break;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
153

154 155
    case GST_MAKE_FOURCC ('P', 'I', 'X', 'L'): /* Miro/Pinnacle fourccs */
    case GST_MAKE_FOURCC ('V', 'I', 'X', 'L'): /* Miro/Pinnacle fourccs */
156
      caps = gst_caps_new_simple ("image/jpeg", NULL);
157
      if (codec_name)
Edward Hervey's avatar
Edward Hervey committed
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
        *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");
177
      break;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
178

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

    case GST_MAKE_FOURCC ('M', 'P', 'E', 'G'):
    case GST_MAKE_FOURCC ('M', 'P', 'G', 'I'):
202 203
    case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
    case GST_MAKE_FOURCC ('M', 'P', 'G', '1'):
204
    case GST_MAKE_FOURCC ('P', 'I', 'M', '1'):
205
    case GST_MAKE_FOURCC (0x01, 0x00, 0x00, 0x10):
David Schleef's avatar
David Schleef committed
206
      caps = gst_caps_new_simple ("video/mpeg",
207
          "systemstream", G_TYPE_BOOLEAN, FALSE,
208
          "mpegversion", G_TYPE_INT, 1, NULL);
209
      if (codec_name)
210
        *codec_name = g_strdup ("MPEG-1 video");
211
      break;
Edward Hervey's avatar
Edward Hervey committed
212

213 214
    case GST_MAKE_FOURCC ('M', 'P', 'G', '2'):
    case GST_MAKE_FOURCC ('m', 'p', 'g', '2'):
Edward Hervey's avatar
Edward Hervey committed
215
    case GST_MAKE_FOURCC ('P', 'I', 'M', '2'):
216
    case GST_MAKE_FOURCC ('D', 'V', 'R', ' '):
217
    case GST_MAKE_FOURCC (0x02, 0x00, 0x00, 0x10):
218 219 220 221
      caps = gst_caps_new_simple ("video/mpeg",
          "systemstream", G_TYPE_BOOLEAN, FALSE,
          "mpegversion", G_TYPE_INT, 2, NULL);
      if (codec_name)
222
        *codec_name = g_strdup ("MPEG-2 video");
223
      break;
224

Edward Hervey's avatar
Edward Hervey committed
225 226 227 228 229 230 231 232
    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
233
    case GST_MAKE_FOURCC ('H', '2', '6', '3'):
234
    case GST_MAKE_FOURCC ('h', '2', '6', '3'):
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
235
    case GST_MAKE_FOURCC ('i', '2', '6', '3'):
236
    case GST_MAKE_FOURCC ('U', '2', '6', '3'):
Edward Hervey's avatar
Edward Hervey committed
237 238
    case GST_MAKE_FOURCC ('v', 'i', 'v', '1'):
    case GST_MAKE_FOURCC ('T', '2', '6', '3'):
239 240
      caps = gst_caps_new_simple ("video/x-h263",
          "variant", G_TYPE_STRING, "itu", NULL);
241
      if (codec_name)
242
        *codec_name = g_strdup ("ITU H.26n");
243
      break;
244

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
245
    case GST_MAKE_FOURCC ('L', '2', '6', '3'):
246 247 248
      /* http://www.leadcodecs.com/Codecs/LEAD-H263.htm */
      caps = gst_caps_new_simple ("video/x-h263",
          "variant", G_TYPE_STRING, "lead", NULL);
249
      if (codec_name)
250
        *codec_name = g_strdup ("Lead H.263");
251
      break;
252

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
253
    case GST_MAKE_FOURCC ('M', '2', '6', '3'):
254
    case GST_MAKE_FOURCC ('m', '2', '6', '3'):
255 256
      caps = gst_caps_new_simple ("video/x-h263",
          "variant", G_TYPE_STRING, "microsoft", NULL);
257
      if (codec_name)
258
        *codec_name = g_strdup ("Microsoft H.263");
259
      break;
260

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
261
    case GST_MAKE_FOURCC ('V', 'D', 'O', 'W'):
262 263
      caps = gst_caps_new_simple ("video/x-h263",
          "variant", G_TYPE_STRING, "vdolive", NULL);
264
      if (codec_name)
265
        *codec_name = g_strdup ("VDOLive");
266
      break;
267

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

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

282 283
      /* apparently not standard H.263...? */
    case GST_MAKE_FOURCC ('I', '2', '6', '3'):
284 285
      caps = gst_caps_new_simple ("video/x-intel-h263",
          "variant", G_TYPE_STRING, "intel", NULL);
286 287 288 289
      if (codec_name)
        *codec_name = g_strdup ("Intel H.263");
      break;

Edward Hervey's avatar
Edward Hervey committed
290 291 292 293 294 295 296
    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;

297 298
    case GST_MAKE_FOURCC ('X', '2', '6', '4'):
    case GST_MAKE_FOURCC ('x', '2', '6', '4'):
299
    case GST_MAKE_FOURCC ('H', '2', '6', '4'):
300
    case GST_MAKE_FOURCC ('h', '2', '6', '4'):
301 302
    case GST_MAKE_FOURCC ('a', 'v', 'c', '1'):
    case GST_MAKE_FOURCC ('A', 'V', 'C', '1'):
303 304
      caps = gst_caps_new_simple ("video/x-h264",
          "variant", G_TYPE_STRING, "itu", NULL);
305 306 307 308 309
      if (codec_name)
        *codec_name = g_strdup ("ITU H.264");
      break;

    case GST_MAKE_FOURCC ('V', 'S', 'S', 'H'):
310 311
      caps = gst_caps_new_simple ("video/x-h264",
          "variant", G_TYPE_STRING, "videosoft", NULL);
312 313 314 315
      if (codec_name)
        *codec_name = g_strdup ("VideoSoft H.264");
      break;

316 317 318 319 320 321 322 323
    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;

324 325 326 327 328 329 330
    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
331 332 333 334 335 336 337
    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
338
    case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
339
    case GST_MAKE_FOURCC ('d', 'i', 'v', '3'):
Edward Hervey's avatar
Edward Hervey committed
340 341
    case GST_MAKE_FOURCC ('D', 'V', 'X', '3'):
    case GST_MAKE_FOURCC ('d', 'v', 'x', '3'):
342
    case GST_MAKE_FOURCC ('D', 'I', 'V', '4'):
343
    case GST_MAKE_FOURCC ('d', 'i', 'v', '4'):
344
    case GST_MAKE_FOURCC ('D', 'I', 'V', '5'):
345
    case GST_MAKE_FOURCC ('d', 'i', 'v', '5'):
346
    case GST_MAKE_FOURCC ('D', 'I', 'V', '6'):
347
    case GST_MAKE_FOURCC ('d', 'i', 'v', '6'):
348 349 350 351 352 353 354
    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
355
      caps = gst_caps_new_simple ("video/x-divx",
356
          "divxversion", G_TYPE_INT, 3, NULL);
357
      if (codec_name)
358
        *codec_name = g_strdup ("DivX MS-MPEG-4 Version 3");
359
      break;
360

361 362
    case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
    case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
363
      caps = gst_caps_new_simple ("video/x-divx",
364
          "divxversion", G_TYPE_INT, 4, NULL);
365
      if (codec_name)
366
        *codec_name = g_strdup ("DivX MPEG-4 Version 4");
367
      break;
368

369 370 371 372 373 374 375
    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
376
    case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
David Schleef's avatar
David Schleef committed
377
      caps = gst_caps_new_simple ("video/x-divx",
378
          "divxversion", G_TYPE_INT, 5, NULL);
379
      if (codec_name)
380
        *codec_name = g_strdup ("DivX MPEG-4 Version 5");
381 382
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
383 384
    case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
    case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
David Schleef's avatar
David Schleef committed
385
      caps = gst_caps_new_simple ("video/x-xvid", NULL);
386
      if (codec_name)
387
        *codec_name = g_strdup ("XVID MPEG-4");
388 389
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
390
    case GST_MAKE_FOURCC ('M', 'P', 'G', '4'):
Edward Hervey's avatar
Edward Hervey committed
391 392
    case GST_MAKE_FOURCC ('M', 'P', '4', '1'):
    case GST_MAKE_FOURCC ('m', 'p', '4', '1'):
David Schleef's avatar
David Schleef committed
393
      caps = gst_caps_new_simple ("video/x-msmpeg",
394
          "msmpegversion", G_TYPE_INT, 41, NULL);
395
      if (codec_name)
396
        *codec_name = g_strdup ("Microsoft MPEG-4 4.1");
397 398
      break;

399
    case GST_MAKE_FOURCC ('m', 'p', '4', '2'):
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
400
    case GST_MAKE_FOURCC ('M', 'P', '4', '2'):
David Schleef's avatar
David Schleef committed
401
      caps = gst_caps_new_simple ("video/x-msmpeg",
402
          "msmpegversion", G_TYPE_INT, 42, NULL);
403
      if (codec_name)
404
        *codec_name = g_strdup ("Microsoft MPEG-4 4.2");
405 406
      break;

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

415
    case GST_MAKE_FOURCC ('M', 'P', '4', 'S'):
416 417 418 419 420 421 422 423
    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'):
424
    case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
Edward Hervey's avatar
Edward Hervey committed
425
    case GST_MAKE_FOURCC ('F', 'F', 'D', 'S'):
426 427 428 429 430 431
      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
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
    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;

452 453
    case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
    case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
454 455
      caps = gst_caps_new_simple ("video/x-msmpeg",
          "msmpegversion", G_TYPE_INT, 43, NULL);
456 457
      if (codec_name)
        *codec_name = g_strdup ("Microsoft MPEG-4 4.3");        /* FIXME? */
458
      break;
459

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
460 461 462
    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);
463
      if (codec_name)
464
        *codec_name = g_strdup ("3ivx");
465 466
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
467 468
    case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
    case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
Edward Hervey's avatar
Edward Hervey committed
469 470
    case GST_MAKE_FOURCC ('d', 'v', 'c', ' '):
    case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
David Schleef's avatar
David Schleef committed
471
      caps = gst_caps_new_simple ("video/x-dv",
472 473
          "systemstream", G_TYPE_BOOLEAN, FALSE,
          "dvversion", G_TYPE_INT, 25, NULL);
474
      if (codec_name)
475
        *codec_name = g_strdup ("Generic DV");
476 477
      break;

Edward Hervey's avatar
Edward Hervey committed
478 479 480 481 482 483 484 485 486
    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;

487 488 489 490 491 492 493 494 495
    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
496
    case GST_MAKE_FOURCC ('W', 'M', 'V', '1'):
David Schleef's avatar
David Schleef committed
497
      caps = gst_caps_new_simple ("video/x-wmv",
498
          "wmvversion", G_TYPE_INT, 1, NULL);
499
      if (codec_name)
500
        *codec_name = g_strdup ("Microsoft Windows Media 7");
501 502
      break;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
503
    case GST_MAKE_FOURCC ('W', 'M', 'V', '2'):
David Schleef's avatar
David Schleef committed
504
      caps = gst_caps_new_simple ("video/x-wmv",
505
          "wmvversion", G_TYPE_INT, 2, NULL);
506
      if (codec_name)
507
        *codec_name = g_strdup ("Microsoft Windows Media 8");
508
      break;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
509 510

    case GST_MAKE_FOURCC ('W', 'M', 'V', '3'):
511
      caps = gst_caps_new_simple ("video/x-wmv",
512
          "wmvversion", G_TYPE_INT, 3, NULL);
513
      if (codec_name)
514
        *codec_name = g_strdup ("Microsoft Windows Media 9");
515 516
      break;

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

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

533 534 535 536 537 538
    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;

539 540 541 542 543 544 545 546 547 548
    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");
549 550
      palette = strf_data;
      strf_data = NULL;
551 552
      break;

553 554 555
    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
556
    case GST_MAKE_FOURCC (0x2, 0x0, 0x0, 0x0): /* why, why, why? */
557 558
      caps = gst_caps_new_simple ("video/x-rle",
          "layout", G_TYPE_STRING, "microsoft", NULL);
559 560
      palette = strf_data;
      strf_data = NULL;
561 562 563 564 565 566 567
      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)
568 569 570
        *codec_name = g_strdup ("Microsoft RLE");
      break;

571 572 573 574 575 576
    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;

577 578 579 580 581
    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");
582 583
      break;

584 585 586 587 588 589 590 591
    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'):
592
    case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
593 594
    case GST_MAKE_FOURCC ('i', 'v', '3', '1'):
    case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
595 596 597 598 599 600
      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;

601 602 603 604 605 606 607 608
    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;

609
    case GST_MAKE_FOURCC ('I', 'V', '5', '0'):
610 611
      caps = gst_caps_new_simple ("video/x-indeo",
          "indeoversion", G_TYPE_INT, 5, NULL);
612 613 614 615
      if (codec_name)
        *codec_name = g_strdup ("Intel Video 5");
      break;

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

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

    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;

725 726 727 728 729 730 731
    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;

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

739 740 741 742 743 744
    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
745 746 747 748 749 750 751 752 753
    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;


754 755 756 757 758 759 760
    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;

761 762 763 764 765 766
    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;

767 768 769 770 771 772 773
    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
774 775 776 777 778 779
    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
780 781 782 783 784 785 786
    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
787

788 789 790 791 792 793 794
    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;

795
    default:
796
      GST_WARNING ("Unknown video fourcc %" GST_FOURCC_FORMAT,
797
          GST_FOURCC_ARGS (codec_fcc));
David Schleef's avatar
David Schleef committed
798
      return NULL;
799 800
  }

David Schleef's avatar
David Schleef committed
801
  if (strh != NULL) {
802 803
    gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
        strh->rate, strh->scale, NULL);
David Schleef's avatar
David Schleef committed
804 805
  } else {
    gst_caps_set_simple (caps,
806
        "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
David Schleef's avatar
David Schleef committed
807 808 809 810
  }

  if (strf != NULL) {
    gst_caps_set_simple (caps,
811 812
        "width", G_TYPE_INT, strf->width,
        "height", G_TYPE_INT, strf->height, NULL);
David Schleef's avatar
David Schleef committed
813 814
  } else {
    gst_caps_set_simple (caps,
815 816
        "width", GST_TYPE_INT_RANGE, 16, 4096,
        "height", GST_TYPE_INT_RANGE, 16, 4096, NULL);
817 818
  }

819 820
  /* extradata */
  if (strf_data || strd_data) {
Wim Taymans's avatar
Wim Taymans committed
821 822 823 824 825
    GstBuffer *codec_data;

    codec_data = strf_data ? strf_data : strd_data;

    gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_data, NULL);
826 827
  }

828
  /* palette */
829 830 831 832 833 834 835 836 837
  if (palette) {
    GstBuffer *copy;
    guint num_colors;

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

838 839
    if (GST_BUFFER_SIZE (palette) >= (num_colors * 4)) {
      /* palette is always at least 256*4 bytes */
840 841
      copy =
          gst_buffer_new_and_alloc (MAX (GST_BUFFER_SIZE (palette), 256 * 4));
842 843
      memcpy (GST_BUFFER_DATA (copy), GST_BUFFER_DATA (palette),
          GST_BUFFER_SIZE (palette));
844 845

#if (G_BYTE_ORDER == G_BIG_ENDIAN)
846 847 848 849 850 851 852 853 854 855
      {
        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);
        }
      }
856
#endif
857 858 859 860 861
      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");
    }
862 863
  }

864 865 866
  return caps;
}

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
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);

912 913 914 915
  /* 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) {
916 917 918 919 920 921 922 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
    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;
}