We are currently experiencing downtime impacting viewing & cloning the Mesa repo, and some GitLab pages returning 503. Please see #freedesktop on IRC for more updates.

gstffmpegcodecmap.c 73.9 KB
Newer Older
1 2
/* GStreamer
 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3
 * This file:
4
 * Copyright (c) 2002-2004 Ronald Bultje <rbultje@ronald.bitfreak.net>
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * 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.
 */

22
#ifdef HAVE_CONFIG_H
23
#include "config.h"
24
#endif
25
#include <gst/gst.h>
26 27 28 29 30
#ifdef HAVE_FFMPEG_UNINSTALLED
#include <avcodec.h>
#else
#include <ffmpeg/avcodec.h>
#endif
31
#include <string.h>
32

33
#include "gstffmpeg.h"
34 35
#include "gstffmpegcodecmap.h"

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
/*
 * Read a palette from a caps.
 */

static void
gst_ffmpeg_get_palette (const GstCaps *caps, AVCodecContext *context)
{
  GstStructure *str = gst_caps_get_structure (caps, 0);
  const GValue *palette_v;
  const GstBuffer *palette;

  /* do we have a palette? */
  if ((palette_v = gst_structure_get_value (str,
          "palette_data")) && context) {
    palette = g_value_get_boxed (palette_v);
    if (GST_BUFFER_SIZE (palette) >= 256 * 4) {
      if (context->palctrl)
        av_free (context->palctrl);
      context->palctrl = av_malloc (sizeof (AVPaletteControl));
      context->palctrl->palette_changed = 1;
      memcpy (context->palctrl->palette, GST_BUFFER_DATA (palette),
          AVPALETTE_SIZE);
    }
  }
}

static void
gst_ffmpeg_set_palette (GstCaps *caps, AVCodecContext *context)
{
  if (context->palctrl) {
    GstBuffer *palette = gst_buffer_new_and_alloc (256 * 4);

    memcpy (GST_BUFFER_DATA (palette), context->palctrl->palette,
        AVPALETTE_SIZE);
    gst_caps_set_simple (caps,
        "palette_data", GST_TYPE_BUFFER, palette, NULL);
  }
}

75 76 77 78
/* this macro makes a caps width fixed or unfixed width/height
 * properties depending on whether we've got a context.
 *
 * See below for why we use this.
79 80 81
 *
 * We should actually do this stuff at the end, like in riff-media.c,
 * but I'm too lazy today. Maybe later.
82 83
 */

84
#define GST_FF_VID_CAPS_NEW(mimetype, ...)			\
David Schleef's avatar
David Schleef committed
85 86 87 88
    (context != NULL) ?						\
    gst_caps_new_simple (mimetype,			      	\
	"width",     G_TYPE_INT,   context->width,	      	\
	"height",    G_TYPE_INT,   context->height,	  	\
89 90
	"framerate", GST_TYPE_FRACTION, context->time_base.den, \
	context->time_base.num,	__VA_ARGS__, NULL)  					\
David Schleef's avatar
David Schleef committed
91 92 93 94
    :	  							\
    gst_caps_new_simple (mimetype,			      	\
	"width",     GST_TYPE_INT_RANGE, 16, 4096,      	\
	"height",    GST_TYPE_INT_RANGE, 16, 4096,	      	\
95 96
	"framerate", GST_TYPE_FRACTION_RANGE, 0, 1,             \
        G_MAXINT, 1, __VA_ARGS__, NULL)
97 98 99 100

/* same for audio - now with channels/sample rate
 */

101
#define GST_FF_AUD_CAPS_NEW(mimetype, ...)			\
David Schleef's avatar
David Schleef committed
102 103 104 105
    (context != NULL) ?					      	\
    gst_caps_new_simple (mimetype,	      			\
	"rate", G_TYPE_INT, context->sample_rate,		\
	"channels", G_TYPE_INT, context->channels,		\
106
	__VA_ARGS__, NULL)					\
David Schleef's avatar
David Schleef committed
107 108
    :								\
    gst_caps_new_simple (mimetype,	      			\
109 110
        "rate", GST_TYPE_INT_RANGE, 8000, 96000,		\
	"channels", GST_TYPE_INT_RANGE, 1, 2,			\
111
	__VA_ARGS__, NULL)
112 113 114 115 116 117

/* Convert a FFMPEG codec ID and optional AVCodecContext
 * to a GstCaps. If the context is ommitted, no fixed values
 * for video/audio size will be included in the GstCaps
 *
 * CodecID is primarily meant for compressed data GstCaps!
118 119 120 121 122 123 124 125 126
 *
 * encode is a special parameter. gstffmpegdec will say
 * FALSE, gstffmpegenc will say TRUE. The output caps
 * depends on this, in such a way that it will be very
 * specific, defined, fixed and correct caps for encoders,
 * yet very wide, "forgiving" caps for decoders. Example
 * for mp3: decode: audio/mpeg,mpegversion=1,layer=[1-3]
 * but encode: audio/mpeg,mpegversion=1,layer=3,bitrate=x,
 * rate=x,channels=x.
127 128
 */

129
GstCaps *
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
130 131
gst_ffmpeg_codecid_to_caps (enum CodecID codec_id,
    AVCodecContext * context, gboolean encode)
132
{
133
  GstCaps *caps = NULL;
134
  gboolean buildcaps = FALSE;
135

136
  switch (codec_id) {
137
    case CODEC_ID_MPEG1VIDEO:
138 139 140 141
      /* For decoding, CODEC_ID_MPEG2VIDEO is preferred... So omit here */
      if (encode) {
        /* FIXME: bitrate */
        caps = GST_FF_VID_CAPS_NEW ("video/mpeg",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
142 143
            "mpegversion", G_TYPE_INT, 1,
            "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
144 145 146 147 148 149 150
      }
      break;

    case CODEC_ID_MPEG2VIDEO:
      if (encode) {
        /* FIXME: bitrate */
        caps = GST_FF_VID_CAPS_NEW ("video/mpeg",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
151 152
            "mpegversion", G_TYPE_INT, 2,
            "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
153 154 155 156
      } else {
        /* decode both MPEG-1 and MPEG-2; width/height/fps are all in
         * the MPEG video stream headers, so may be omitted from caps. */
        caps = gst_caps_new_simple ("video/mpeg",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
157 158
            "mpegversion", GST_TYPE_INT_RANGE, 1, 2,
            "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
159
      }
160
      break;
161 162 163 164 165

    case CODEC_ID_MPEG2VIDEO_XVMC:
      /* this is a special ID - don't need it in GStreamer, I think */
      break;

Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
166
      /* I don't know the exact differences between those... Anyone? */
167
    case CODEC_ID_H263:
168
    case CODEC_ID_H263P:
169
      caps = GST_FF_VID_CAPS_NEW ("video/x-h263", NULL);
170
      break;
171

172 173 174 175
    case CODEC_ID_H263I:
      caps = GST_FF_VID_CAPS_NEW ("video/x-intel-h263", NULL);
      break;

176 177 178 179
    case CODEC_ID_H261:
      caps = GST_FF_VID_CAPS_NEW ("video/x-h261", NULL);
      break;

180
    case CODEC_ID_RV10:
181
    case CODEC_ID_RV20:
182
      {
183 184 185 186
        gint version = (codec_id == CODEC_ID_RV10) ? 1 : 2;

        /* FIXME: context->sub_id must be filled in during decoding */
        caps = GST_FF_VID_CAPS_NEW ("video/x-pn-realvideo",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
187 188
            "systemstream", G_TYPE_BOOLEAN, FALSE,
            "rmversion", G_TYPE_INT, version, NULL);
189 190 191 192
        if (context) {
          gst_caps_set_simple (caps,
              "rmsubid", GST_TYPE_FOURCC, context->sub_id, NULL);
        }
193
      }
194
      break;
195

196
    case CODEC_ID_MP2:
197 198 199 200
      /* we use CODEC_ID_MP3 for decoding */
      if (encode) {
        /* FIXME: bitrate */
        caps = GST_FF_AUD_CAPS_NEW ("audio/mpeg",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
201
            "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 2, NULL);
202
      }
203
      break;
204

205 206 207 208
    case CODEC_ID_MP3:
      if (encode) {
        /* FIXME: bitrate */
        caps = GST_FF_AUD_CAPS_NEW ("audio/mpeg",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
209
            "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 3, NULL);
210 211 212 213
      } else {
        /* Decodes MPEG-1 layer 1/2/3. Samplerate, channels et al are
         * in the MPEG audio header, so may be omitted from caps. */
        caps = gst_caps_new_simple ("audio/mpeg",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
214 215
            "mpegversion", G_TYPE_INT, 1,
            "layer", GST_TYPE_INT_RANGE, 1, 3, NULL);
216
      }
217
      break;
218

David Schleef's avatar
David Schleef committed
219
    case CODEC_ID_VORBIS:
220 221 222 223 224 225 226
      /* This one is disabled for several reasons:
       * - GStreamer already has perfect Ogg and Vorbis support
       * - The ffmpeg implementation depends on libvorbis/libogg,
       *   which are not included in the ffmpeg that GStreamer ships.
       * - The ffmpeg implementation depends on shared objects between
       *   the ogg demuxer and vorbis decoder, which GStreamer doesn't.
       */
227
      break;
228

229
    case CODEC_ID_AC3:
230 231 232 233 234 235
      /* Decoding is disabled, because:
       * - it depends on liba52, which we don't ship in ffmpeg.
       * - we already have a liba52 plugin ourselves.
       */
      if (encode) {
        /* FIXME: bitrate */
236
        caps = GST_FF_AUD_CAPS_NEW ("audio/x-ac3", NULL);
237
      }
238
      break;
239

Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
240 241 242 243 244
      /* MJPEG is normal JPEG, Motion-JPEG and Quicktime MJPEG-A. MJPEGB
       * is Quicktime's MJPEG-B. LJPEG is lossless JPEG. I don't know what
       * sp5x is, but it's apparently something JPEG... We don't separate
       * between those in GStreamer. Should we (at least between MJPEG,
       * MJPEG-B and sp5x decoding...)? */
245
    case CODEC_ID_MJPEG:
246 247
    case CODEC_ID_LJPEG:
    case CODEC_ID_SP5X:
248
      caps = GST_FF_VID_CAPS_NEW ("image/jpeg", NULL);
Wim Taymans's avatar
Wim Taymans committed
249
      break;
250

251 252 253 254
    case CODEC_ID_MJPEGB:
      caps = GST_FF_VID_CAPS_NEW ("video/x-mjpeg-b", NULL);
      break;

255
    case CODEC_ID_MPEG4:
256
      if (encode && context != NULL) {
257 258
        /* I'm not exactly sure what ffmpeg outputs... ffmpeg itself uses
         * the AVI fourcc 'DIVX', but 'mp4v' for Quicktime... */
259
        switch (context->codec_tag) {
260 261 262 263 264 265 266 267 268 269 270 271
          case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
            caps = GST_FF_VID_CAPS_NEW ("video/x-divx",
	        "divxversion", G_TYPE_INT, 5, NULL);
            break;
          case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
          default:
            /* FIXME: bitrate */
            caps = GST_FF_VID_CAPS_NEW ("video/mpeg",
                "systemstream", G_TYPE_BOOLEAN, FALSE,
                "mpegversion", G_TYPE_INT, 4, NULL);
            break;
        }
272 273 274
      } else {
        /* The trick here is to separate xvid, divx, mpeg4, 3ivx et al */
        caps = GST_FF_VID_CAPS_NEW ("video/mpeg",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
275 276
            "mpegversion", G_TYPE_INT, 4,
            "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
277 278 279 280 281 282 283 284 285
        if (encode) {
          gst_caps_append (caps, GST_FF_VID_CAPS_NEW ("video/x-divx",
              "divxversion", G_TYPE_INT, 5, NULL));
        } else {
          gst_caps_append (caps, GST_FF_VID_CAPS_NEW ("video/x-divx",
              "divxversion", GST_TYPE_INT_RANGE, 4, 5, NULL));
          gst_caps_append (caps, GST_FF_VID_CAPS_NEW ("video/x-xvid", NULL));
          gst_caps_append (caps, GST_FF_VID_CAPS_NEW ("video/x-3ivx", NULL));
        }
286
      }
287
      break;
288

289
    case CODEC_ID_RAWVIDEO:
290
      caps = gst_ffmpeg_codectype_to_caps (CODEC_TYPE_VIDEO, context);
291
      break;
292

293
    case CODEC_ID_MSMPEG4V1:
294 295
    case CODEC_ID_MSMPEG4V2:
    case CODEC_ID_MSMPEG4V3:
296
      {
297 298 299 300
        gint version = 41 + codec_id - CODEC_ID_MSMPEG4V1;

        /* encode-FIXME: bitrate */
        caps = GST_FF_VID_CAPS_NEW ("video/x-msmpeg",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
301
            "msmpegversion", G_TYPE_INT, version, NULL);
302 303
        if (!encode && codec_id == CODEC_ID_MSMPEG4V3) {
          gst_caps_append (caps, GST_FF_VID_CAPS_NEW ("video/x-divx",
304
              "divxversion", G_TYPE_INT, 3, NULL));
305
        }
306
      }
307
      break;
308

309
    case CODEC_ID_WMV1:
310
    case CODEC_ID_WMV2:
311
      {
312 313
        gint version = (codec_id == CODEC_ID_WMV1) ? 1 : 2;

314
        caps = GST_FF_VID_CAPS_NEW ("video/x-wmv",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
315
            "wmvversion", G_TYPE_INT, version, NULL);
316
      }
317
      break;
318

319 320
    case CODEC_ID_FLV1:
      buildcaps = TRUE;
321
      break;
322

323
    case CODEC_ID_SVQ1:
David Schleef's avatar
David Schleef committed
324
      caps = GST_FF_VID_CAPS_NEW ("video/x-svq",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
325
          "svqversion", G_TYPE_INT, 1, NULL);
326
      break;
327 328

    case CODEC_ID_SVQ3:
David Schleef's avatar
David Schleef committed
329
      caps = GST_FF_VID_CAPS_NEW ("video/x-svq",
330
          "svqversion", G_TYPE_INT, 3, NULL);
331
      break;
332

333
    case CODEC_ID_DVAUDIO:
334
      caps = GST_FF_AUD_CAPS_NEW ("audio/x-dv", NULL);
335
      break;
336

337
    case CODEC_ID_DVVIDEO:
338 339 340
      caps = GST_FF_VID_CAPS_NEW ("video/x-dv",
          "systemstream", G_TYPE_BOOLEAN, FALSE,
          NULL);
341
      break;
342

343 344
    case CODEC_ID_WMAV1:
    case CODEC_ID_WMAV2:
345
      {
346 347
        gint version = (codec_id == CODEC_ID_WMAV1) ? 1 : 2;

348
        if (context) {
349 350 351 352
          caps = GST_FF_AUD_CAPS_NEW ("audio/x-wma",
             "wmaversion", G_TYPE_INT, version,
             "block_align", G_TYPE_INT, context->block_align,
             "bitrate", G_TYPE_INT, context->bit_rate, NULL);
353
        } else {
354 355 356 357 358
          caps = GST_FF_AUD_CAPS_NEW ("audio/x-wma",
             "wmaversion", G_TYPE_INT, version,
             "block_align", GST_TYPE_INT_RANGE, 0, G_MAXINT,
             "bitrate", GST_TYPE_INT_RANGE, 0, G_MAXINT, NULL);
        }
359
      }
360
      break;
361

362 363
    case CODEC_ID_MACE3:
    case CODEC_ID_MACE6:
364
      {
365 366 367
        gint version = (codec_id == CODEC_ID_MACE3) ? 3 : 6;

        caps = GST_FF_AUD_CAPS_NEW ("audio/x-mace",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
368
            "maceversion", G_TYPE_INT, version, NULL);
369
      }
370
      break;
371

Wim Taymans's avatar
Wim Taymans committed
372
    case CODEC_ID_HUFFYUV:
373
      caps = GST_FF_VID_CAPS_NEW ("video/x-huffyuv", NULL);
374 375 376 377
      if (context) {
        gst_caps_set_simple (caps,
            "bpp", G_TYPE_INT, context->bits_per_sample, NULL);
      }
378 379 380
      break;

    case CODEC_ID_CYUV:
381
      buildcaps = TRUE;
382 383 384
      break;

    case CODEC_ID_H264:
385
      caps = GST_FF_VID_CAPS_NEW ("video/x-h264", NULL);
386 387 388
      break;

    case CODEC_ID_INDEO3:
David Schleef's avatar
David Schleef committed
389
      caps = GST_FF_VID_CAPS_NEW ("video/x-indeo",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
390
          "indeoversion", G_TYPE_INT, 3, NULL);
391 392
      break;

393 394 395 396 397
    case CODEC_ID_INDEO2:
      caps = GST_FF_VID_CAPS_NEW ("video/x-indeo",
          "indeoversion", G_TYPE_INT, 2, NULL);
      break;

398
    case CODEC_ID_VP3:
399
      caps = GST_FF_VID_CAPS_NEW ("video/x-vp3", NULL);
400 401
      break;

402
    case CODEC_ID_THEORA:
403
      caps = GST_FF_VID_CAPS_NEW ("video/x-theora", NULL);
404 405
      break;

406
    case CODEC_ID_AAC:
407
    case CODEC_ID_MPEG4AAC:
408 409
      caps = GST_FF_AUD_CAPS_NEW ("audio/mpeg",
          "mpegversion", G_TYPE_INT, 4, NULL);
410 411 412
      break;

    case CODEC_ID_ASV1:
413 414
    case CODEC_ID_ASV2:
      buildcaps = TRUE;
415 416
      break;

417
    case CODEC_ID_FFV1:
David Schleef's avatar
David Schleef committed
418
      caps = GST_FF_VID_CAPS_NEW ("video/x-ffv",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
419
          "ffvversion", G_TYPE_INT, 1, NULL);
420 421 422
      break;

    case CODEC_ID_4XM:
423
      caps = GST_FF_VID_CAPS_NEW ("video/x-4xm", NULL);
424 425
      break;

426 427 428 429 430 431
    case CODEC_ID_XAN_WC3:
    case CODEC_ID_XAN_WC4:
      caps = GST_FF_VID_CAPS_NEW ("video/x-xan",
          "wcversion", G_TYPE_INT, 3 - CODEC_ID_XAN_WC3 + codec_id, NULL);
      break;

432
    case CODEC_ID_FRAPS:
433 434 435 436 437 438 439 440
    case CODEC_ID_VCR1:
    case CODEC_ID_CLJR:
    case CODEC_ID_MDEC:
    case CODEC_ID_ROQ:
    case CODEC_ID_INTERPLAY_VIDEO:
      buildcaps = TRUE;
      break;

441 442 443 444
    case CODEC_ID_RPZA:
      caps = GST_FF_VID_CAPS_NEW ("video/x-apple-video", NULL);
      break;

445
    case CODEC_ID_CINEPAK:
446
      caps = GST_FF_VID_CAPS_NEW ("video/x-cinepak", NULL);
447 448
      break;

449 450 451 452 453 454 455 456 457 458 459 460 461
    /* WS_VQA belogns here (order) */

    case CODEC_ID_MSRLE:
      caps = GST_FF_VID_CAPS_NEW ("video/x-rle",
	  "layout", G_TYPE_STRING, "microsoft", NULL);
      if (context) {
        gst_caps_set_simple (caps,
	    "depth", G_TYPE_INT, (gint) context->bits_per_sample, NULL);
      } else {
        gst_caps_set_simple (caps, "depth", GST_TYPE_INT_RANGE, 1, 64, NULL);
      }
      break;

462 463 464 465 466 467 468 469 470 471 472
    case CODEC_ID_QTRLE:
      caps = GST_FF_VID_CAPS_NEW ("video/x-rle",
          "layout", G_TYPE_STRING, "quicktime", NULL);
      if (context) {
        gst_caps_set_simple (caps,
            "depth", G_TYPE_INT, (gint) context->bits_per_sample, NULL);
      } else {
        gst_caps_set_simple (caps, "depth", GST_TYPE_INT_RANGE, 1, 64, NULL);
      }
      break;

473 474 475 476 477
    case CODEC_ID_MSVIDEO1:
      caps = GST_FF_VID_CAPS_NEW ("video/x-msvideocodec",
	  "msvideoversion", G_TYPE_INT, 1, NULL);
      break;

478 479 480 481 482
    case CODEC_ID_WMV3:
    case CODEC_ID_VC9:
      caps = GST_FF_VID_CAPS_NEW ("video/x-wmv",
          "wmvversion", G_TYPE_INT, 3, NULL);
      break;
483 484 485
    case CODEC_ID_QDM2:
      caps = GST_FF_AUD_CAPS_NEW ("audio/x-qdm2", NULL);
      break;  
486

487 488 489 490 491 492
    case CODEC_ID_WS_VQA:
    case CODEC_ID_IDCIN:
    case CODEC_ID_8BPS:
    case CODEC_ID_SMC:
    case CODEC_ID_FLIC:
    case CODEC_ID_TRUEMOTION1:
493
    case CODEC_ID_TRUEMOTION2:
494 495 496 497
    case CODEC_ID_VMDVIDEO:
    case CODEC_ID_VMDAUDIO:
    case CODEC_ID_MSZH:
    case CODEC_ID_ZLIB:
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
    case CODEC_ID_SONIC:
    case CODEC_ID_SONIC_LS:
    case CODEC_ID_SNOW:
    case CODEC_ID_TSCC:
    case CODEC_ID_ULTI:
    case CODEC_ID_QDRAW:
    case CODEC_ID_VIXL:
    case CODEC_ID_QPEG:
    case CODEC_ID_XVID:
    case CODEC_ID_PNG:
    case CODEC_ID_PPM:
    case CODEC_ID_PBM:
    case CODEC_ID_PGM:
    case CODEC_ID_PGMYUV:
    case CODEC_ID_PAM:
    case CODEC_ID_FFVHUFF:
514 515 516 517 518 519
    case CODEC_ID_LOCO:
    case CODEC_ID_WNV1:
    case CODEC_ID_AASC:
    case CODEC_ID_MP3ADU:
    case CODEC_ID_MP3ON4:
    case CODEC_ID_WESTWOOD_SND1:
520 521 522
      buildcaps = TRUE;
      break;

Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
523
      /* weird quasi-codecs for the demuxers only */
524 525 526 527 528 529
    case CODEC_ID_PCM_S16LE:
    case CODEC_ID_PCM_S16BE:
    case CODEC_ID_PCM_U16LE:
    case CODEC_ID_PCM_U16BE:
    case CODEC_ID_PCM_S8:
    case CODEC_ID_PCM_U8:
530
      {
531
        gint width = 0, depth = 0, endianness = 0;
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
532
        gboolean signedness = FALSE;    /* blabla */
533 534 535

        switch (codec_id) {
          case CODEC_ID_PCM_S16LE:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
536 537
            width = 16;
            depth = 16;
538 539 540 541
            endianness = G_LITTLE_ENDIAN;
            signedness = TRUE;
            break;
          case CODEC_ID_PCM_S16BE:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
542 543
            width = 16;
            depth = 16;
544 545 546 547
            endianness = G_BIG_ENDIAN;
            signedness = TRUE;
            break;
          case CODEC_ID_PCM_U16LE:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
548 549
            width = 16;
            depth = 16;
550 551 552 553
            endianness = G_LITTLE_ENDIAN;
            signedness = FALSE;
            break;
          case CODEC_ID_PCM_U16BE:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
554 555
            width = 16;
            depth = 16;
556 557 558 559
            endianness = G_BIG_ENDIAN;
            signedness = FALSE;
            break;
          case CODEC_ID_PCM_S8:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
560 561
            width = 8;
            depth = 8;
562 563 564 565
            endianness = G_BYTE_ORDER;
            signedness = TRUE;
            break;
          case CODEC_ID_PCM_U8:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
566 567
            width = 8;
            depth = 8;
568 569 570 571
            endianness = G_BYTE_ORDER;
            signedness = FALSE;
            break;
          default:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
572
            g_assert (0);       /* don't worry, we never get here */
573 574 575
            break;
        }

David Schleef's avatar
David Schleef committed
576
        caps = GST_FF_AUD_CAPS_NEW ("audio/x-raw-int",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
577 578 579 580
            "width", G_TYPE_INT, width,
            "depth", G_TYPE_INT, depth,
            "endianness", G_TYPE_INT, endianness,
            "signed", G_TYPE_BOOLEAN, signedness, NULL);
581
      }
582 583
      break;

584
    case CODEC_ID_PCM_MULAW:
585
      caps = GST_FF_AUD_CAPS_NEW ("audio/x-mulaw", NULL);
586 587 588
      break;

    case CODEC_ID_PCM_ALAW:
589
      caps = GST_FF_AUD_CAPS_NEW ("audio/x-alaw", NULL);
590 591
      break;

592 593
    case CODEC_ID_ADPCM_IMA_QT:
    case CODEC_ID_ADPCM_IMA_WAV:
594 595 596 597
    case CODEC_ID_ADPCM_IMA_DK3:
    case CODEC_ID_ADPCM_IMA_DK4:
    case CODEC_ID_ADPCM_IMA_WS:
    case CODEC_ID_ADPCM_IMA_SMJPEG:
598
    case CODEC_ID_ADPCM_MS:
599
    case CODEC_ID_ADPCM_4XM:
600 601 602 603
    case CODEC_ID_ADPCM_XA:
    case CODEC_ID_ADPCM_ADX:
    case CODEC_ID_ADPCM_EA:
    case CODEC_ID_ADPCM_G726:
604
    case CODEC_ID_ADPCM_CT:
605
    case CODEC_ID_ADPCM_SWF:
606
    case CODEC_ID_ADPCM_YAMAHA:
607
      {
608 609 610 611 612 613 614
        gchar *layout = NULL;

        switch (codec_id) {
          case CODEC_ID_ADPCM_IMA_QT:
            layout = "quicktime";
            break;
          case CODEC_ID_ADPCM_IMA_WAV:
615
            layout = "dvi";
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
            break;
          case CODEC_ID_ADPCM_IMA_DK3:
            layout = "dk3";
            break;
          case CODEC_ID_ADPCM_IMA_DK4:
            layout = "dk4";
            break;
          case CODEC_ID_ADPCM_IMA_WS:
            layout = "westwood";
            break;
          case CODEC_ID_ADPCM_IMA_SMJPEG:
            layout = "smjpeg";
            break;
          case CODEC_ID_ADPCM_MS:
            layout = "microsoft";
            break;
          case CODEC_ID_ADPCM_4XM:
            layout = "4xm";
            break;
          case CODEC_ID_ADPCM_XA:
            layout = "xa";
            break;
          case CODEC_ID_ADPCM_ADX:
            layout = "adx";
            break;
          case CODEC_ID_ADPCM_EA:
            layout = "ea";
            break;
          case CODEC_ID_ADPCM_G726:
            layout = "g726";
            break;
647 648 649
          case CODEC_ID_ADPCM_CT:
            layout = "ct";
            break;
650 651 652
          case CODEC_ID_ADPCM_SWF:
            layout = "swf";
            break;
653 654 655
          case CODEC_ID_ADPCM_YAMAHA:
            layout = "yamaha";
            break;
656
          default:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
657
            g_assert (0);       /* don't worry, we never get here */
658 659 660 661 662 663
            break;
        }

        /* FIXME: someone please check whether we need additional properties
         * in this caps definition. */
        caps = GST_FF_AUD_CAPS_NEW ("audio/x-adpcm",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
664
            "layout", G_TYPE_STRING, layout, NULL);
665 666 667 668
        if (context)
          gst_caps_set_simple (caps,
              "block_align", G_TYPE_INT, context->block_align,
              "bitrate", G_TYPE_INT, context->bit_rate, NULL);
669
      }
670 671 672
      break;

    case CODEC_ID_AMR_NB:
673 674 675
      caps = GST_FF_AUD_CAPS_NEW ("audio/x-amr-nb", NULL);
      break;

676
    case CODEC_ID_AMR_WB:
677
      caps = GST_FF_AUD_CAPS_NEW ("audio/x-amr-wb", NULL);
678 679
      break;

680
    case CODEC_ID_RA_144:
681
    case CODEC_ID_RA_288:
682
      {
683 684 685 686
        gint version = (codec_id == CODEC_ID_RA_144) ? 1 : 2;

        /* FIXME: properties? */
        caps = GST_FF_AUD_CAPS_NEW ("audio/x-pn-realaudio",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
687
            "raversion", G_TYPE_INT, version, NULL);
688
      }
689
      break;
690

691 692 693
    case CODEC_ID_ROQ_DPCM:
    case CODEC_ID_INTERPLAY_DPCM:
    case CODEC_ID_XAN_DPCM:
694
    case CODEC_ID_SOL_DPCM:
695
      {
696 697 698 699 700 701 702 703 704 705 706 707
        gchar *layout = NULL;

        switch (codec_id) {
          case CODEC_ID_ROQ_DPCM:
            layout = "roq";
            break;
          case CODEC_ID_INTERPLAY_DPCM:
            layout = "interplay";
            break;
          case CODEC_ID_XAN_DPCM:
            layout = "xan";
            break;
708 709 710
          case CODEC_ID_SOL_DPCM:
            layout = "sol";
            break;
711
          default:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
712
            g_assert (0);       /* don't worry, we never get here */
713 714 715 716 717 718
            break;
        }

        /* FIXME: someone please check whether we need additional properties
         * in this caps definition. */
        caps = GST_FF_AUD_CAPS_NEW ("audio/x-dpcm",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
719
            "layout", G_TYPE_STRING, layout, NULL);
720 721 722 723
        if (context)
          gst_caps_set_simple (caps,
              "block_align", G_TYPE_INT, context->block_align,
              "bitrate", G_TYPE_INT, context->bit_rate, NULL);
724
      }
725
      break;
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
726

727 728 729 730 731 732 733 734 735 736 737 738
    case CODEC_ID_SHORTEN:
      caps = gst_caps_new_simple ("audio/x-shorten", NULL);
      break;

    case CODEC_ID_ALAC:
      caps = GST_FF_AUD_CAPS_NEW ("audio/x-alac", NULL);
      if (context) {
        gst_caps_set_simple (caps,
            "samplesize", G_TYPE_INT, context->bits_per_sample, NULL);
      }
      break;

739 740 741 742 743 744
    case CODEC_ID_FLAC:
      /* Note that ffmpeg has no encoder yet, but just for safety. In the
       * encoder case, we want to add things like samplerate, channels... */
      if (!encode) {
        caps = gst_caps_new_simple ("audio/x-flac", NULL);
      }
745 746
      break;

747 748 749 750 751
    case CODEC_ID_DVD_SUBTITLE:
    case CODEC_ID_DVB_SUBTITLE:
      caps = NULL;
      break;

752
    default:
753
      g_warning ("Unknown codec ID %d, please add here", codec_id);
754 755 756
      break;
  }

757 758 759 760 761 762 763 764 765 766
  if (buildcaps) {
    AVCodec *codec;

    if ((codec = avcodec_find_decoder (codec_id)) ||
        (codec = avcodec_find_encoder (codec_id))) {
      gchar *mime = NULL;

      switch (codec->type) {
        case CODEC_TYPE_VIDEO:
          mime = g_strdup_printf ("video/x-gst_ff-%s", codec->name);
767
          caps = GST_FF_VID_CAPS_NEW (mime, NULL);
768 769 770 771
          g_free (mime);
          break;
        case CODEC_TYPE_AUDIO:
          mime = g_strdup_printf ("audio/x-gst_ff-%s", codec->name);
772
          caps = GST_FF_AUD_CAPS_NEW (mime, NULL);
773
          if (context)
774 775 776
            gst_caps_set_simple (caps,
                "block_align", G_TYPE_INT, context->block_align,
                "bitrate", G_TYPE_INT, context->bit_rate, NULL);
777 778 779 780 781 782 783 784
          g_free (mime);
          break;
        default:
          break;
      }
    }
  }

785
  if (caps != NULL) {
786 787 788 789

    /* set private data */
    if (context && context->extradata_size > 0) {
      GstBuffer *data = gst_buffer_new_and_alloc (context->extradata_size);
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
790

791 792 793 794 795 796 797
      memcpy (GST_BUFFER_DATA (data), context->extradata,
          context->extradata_size);
      gst_caps_set_simple (caps,
          "codec_data", GST_TYPE_BUFFER, data, NULL);
      gst_buffer_unref (data);
    }

798 799 800 801 802
    /* palette */
    if (context) {
      gst_ffmpeg_set_palette (caps, context);
    }

803
    GST_DEBUG ("caps for codec_id=%d: %" GST_PTR_FORMAT, codec_id, caps);
804

805
  } else {
David Schleef's avatar
David Schleef committed
806
    GST_WARNING ("No caps found for codec_id=%d", codec_id);
807 808 809 810 811 812 813 814 815 816 817 818 819
  }

  return caps;
}

/* Convert a FFMPEG Pixel Format and optional AVCodecContext
 * to a GstCaps. If the context is ommitted, no fixed values
 * for video/audio size will be included in the GstCaps
 *
 * See below for usefullness
 */

static GstCaps *
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
820
gst_ffmpeg_pixfmt_to_caps (enum PixelFormat pix_fmt, AVCodecContext * context)
821 822 823 824
{
  GstCaps *caps = NULL;

  int bpp = 0, depth = 0, endianness = 0;
825
  gulong g_mask = 0, r_mask = 0, b_mask = 0, a_mask = 0;
826
  guint32 fmt = 0;
827
  
828
  switch (pix_fmt) {
829
    case PIX_FMT_YUVJ420P:
830
    case PIX_FMT_YUV420P:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
831
      fmt = GST_MAKE_FOURCC ('I', '4', '2', '0');
832 833
      break;
    case PIX_FMT_YUV422:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
834
      fmt = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
835 836 837 838
      break;
    case PIX_FMT_RGB24:
      bpp = depth = 24;
      endianness = G_BIG_ENDIAN;
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
839 840 841
      r_mask = 0xff0000;
      g_mask = 0x00ff00;
      b_mask = 0x0000ff;
842 843 844
      break;
    case PIX_FMT_BGR24:
      bpp = depth = 24;
845
      endianness = G_BIG_ENDIAN;
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
846 847 848
      r_mask = 0x0000ff;
      g_mask = 0x00ff00;
      b_mask = 0xff0000;
849
      break;
850
    case PIX_FMT_YUVJ422P:
851
    case PIX_FMT_YUV422P:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
852
      fmt = GST_MAKE_FOURCC ('Y', '4', '2', 'B');
853
      break;
854
    case PIX_FMT_YUVJ444P:
855
    case PIX_FMT_YUV444P:
856
      fmt = GST_MAKE_FOURCC ('Y', '4', '4', '4');
857 858
      break;
    case PIX_FMT_RGBA32:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
859
      bpp = 32;
860
      depth = 32;
861 862
      endianness = G_BIG_ENDIAN;
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
863
      r_mask = 0x000000ff;
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
864
      g_mask = 0x0000ff00;
865 866
      b_mask = 0x00ff0000;
      a_mask = 0xff000000;
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
867
#else
868
      r_mask = 0xff000000;
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
869
      g_mask = 0x00ff0000;
870 871
      b_mask = 0x0000ff00;
      a_mask = 0x000000ff;
872
#endif
873 874
      break;
    case PIX_FMT_YUV410P:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
875
      fmt = GST_MAKE_FOURCC ('Y', 'U', 'V', '9');
876 877
      break;
    case PIX_FMT_YUV411P:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
878
      fmt = GST_MAKE_FOURCC ('Y', '4', '1', 'B');
879 880 881 882
      break;
    case PIX_FMT_RGB565:
      bpp = depth = 16;
      endianness = G_BYTE_ORDER;
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
883 884 885
      r_mask = 0xf800;
      g_mask = 0x07e0;
      b_mask = 0x001f;
886 887
      break;
    case PIX_FMT_RGB555:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
888 889
      bpp = 16;
      depth = 15;
890
      endianness = G_BYTE_ORDER;
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
891 892 893
      r_mask = 0x7c00;
      g_mask = 0x03e0;
      b_mask = 0x001f;
894
      break;
895 896 897 898
    case PIX_FMT_PAL8:
      bpp = depth = 8;
      endianness = G_BYTE_ORDER;
      break;
899 900 901 902 903 904
    case PIX_FMT_GRAY8:
      bpp = depth = 8;
      caps = GST_FF_VID_CAPS_NEW ("video/x-raw-gray",
				  "bpp", G_TYPE_INT, bpp,
				  "depth", G_TYPE_INT, depth, NULL);
      break;
905 906 907 908
    default:
      /* give up ... */
      break;
  }
909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930
  
  if (caps == NULL) {
    if (bpp != 0) {
      if (r_mask != 0) {
	caps = GST_FF_VID_CAPS_NEW ("video/x-raw-rgb",
				    "bpp", G_TYPE_INT, bpp,
				    "depth", G_TYPE_INT, depth,
				    "red_mask", G_TYPE_INT, r_mask,
				    "green_mask", G_TYPE_INT, g_mask,
				    "blue_mask", G_TYPE_INT, b_mask,
				    "endianness", G_TYPE_INT, endianness, NULL);
	if (a_mask) {
	  gst_caps_set_simple (caps, "alpha_mask", G_TYPE_INT, a_mask, NULL);
	}
      } else {
	caps = GST_FF_VID_CAPS_NEW ("video/x-raw-rgb",
				    "bpp", G_TYPE_INT, bpp,
				    "depth", G_TYPE_INT, depth,
				    "endianness", G_TYPE_INT, endianness, NULL);
	if (context) {
	  gst_ffmpeg_set_palette (caps, context);
	}
931
      }
932 933 934
    } else if (fmt) {
      caps = GST_FF_VID_CAPS_NEW ("video/x-raw-yuv",
				  "format", GST_TYPE_FOURCC, fmt, NULL);
935
    }
936 937 938
  }

  if (caps != NULL) {
David Schleef's avatar
David Schleef committed
939
    char *str = gst_caps_to_string (caps);
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
940

David Schleef's avatar
David Schleef committed
941
    GST_DEBUG ("caps for pix_fmt=%d: %s", pix_fmt, str);
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
942
    g_free (str);
943
  } else {
David Schleef's avatar
David Schleef committed
944
    GST_WARNING ("No caps found for pix_fmt=%d", pix_fmt);
945 946 947 948 949 950 951 952 953 954 955 956 957
  }

  return caps;
}

/* Convert a FFMPEG Sample Format and optional AVCodecContext
 * to a GstCaps. If the context is ommitted, no fixed values
 * for video/audio size will be included in the GstCaps
 *
 * See below for usefullness
 */

static GstCaps *
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
958 959
gst_ffmpeg_smpfmt_to_caps (enum SampleFormat sample_fmt,
    AVCodecContext * context)
960 961 962 963 964 965 966 967 968 969
{
  GstCaps *caps = NULL;

  int bpp = 0;
  gboolean signedness = FALSE;

  switch (sample_fmt) {
    case SAMPLE_FMT_S16:
      signedness = TRUE;
      bpp = 16;
970
      break;
971

972
    default:
973
      /* .. */
974 975 976
      break;
  }

977
  if (bpp) {
David Schleef's avatar
David Schleef committed
978
    caps = GST_FF_AUD_CAPS_NEW ("audio/x-raw-int",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
979 980 981
        "signed", G_TYPE_BOOLEAN, signedness,
        "endianness", G_TYPE_INT, G_BYTE_ORDER,
        "width", G_TYPE_INT, bpp, "depth", G_TYPE_INT, bpp, NULL);
982 983 984
  }

  if (caps != NULL) {
David Schleef's avatar
David Schleef committed
985
    char *str = gst_caps_to_string (caps);
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
986

David Schleef's avatar
David Schleef committed
987
    GST_DEBUG ("caps for sample_fmt=%d: %s", sample_fmt, str);
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
988
    g_free (str);
989
  } else {
David Schleef's avatar
David Schleef committed
990
    GST_WARNING ("No caps found for sample_fmt=%d", sample_fmt);
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
  }

  return caps;
}

/* Convert a FFMPEG codec Type and optional AVCodecContext
 * to a GstCaps. If the context is ommitted, no fixed values
 * for video/audio size will be included in the GstCaps
 *
 * CodecType is primarily meant for uncompressed data GstCaps!
 */

GstCaps *