gstffmpegcodecmap.c 74 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
	"framerate", G_TYPE_DOUBLE, (double) 1. *		\
90 91
				context->time_base.den /	\
					context->time_base.num,	\
92
	__VA_ARGS__, NULL)  					\
David Schleef's avatar
David Schleef committed
93 94 95 96
    :	  							\
    gst_caps_new_simple (mimetype,			      	\
	"width",     GST_TYPE_INT_RANGE, 16, 4096,      	\
	"height",    GST_TYPE_INT_RANGE, 16, 4096,	      	\
97
	"framerate", GST_TYPE_DOUBLE_RANGE, (double) 1., 	\
98
						G_MAXDOUBLE,	\
99
	__VA_ARGS__, NULL)
100 101 102 103

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

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

/* 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!
121 122 123 124 125 126 127 128 129
 *
 * 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.
130 131
 */

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

139
  switch (codec_id) {
140
    case CODEC_ID_MPEG1VIDEO:
141 142 143 144
      /* 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
145 146
            "mpegversion", G_TYPE_INT, 1,
            "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
147 148 149 150 151 152 153
      }
      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
154 155
            "mpegversion", G_TYPE_INT, 2,
            "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
156 157 158 159
      } 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
160 161
            "mpegversion", GST_TYPE_INT_RANGE, 1, 2,
            "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
162
      }
163
      break;
164 165 166 167 168

    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
169
      /* I don't know the exact differences between those... Anyone? */
170
    case CODEC_ID_H263:
171
    case CODEC_ID_H263P:
172
      caps = GST_FF_VID_CAPS_NEW ("video/x-h263", NULL);
173
      break;
174

175 176 177 178
    case CODEC_ID_H263I:
      caps = GST_FF_VID_CAPS_NEW ("video/x-intel-h263", NULL);
      break;

179 180 181 182
    case CODEC_ID_H261:
      caps = GST_FF_VID_CAPS_NEW ("video/x-h261", NULL);
      break;

183
    case CODEC_ID_RV10:
184
    case CODEC_ID_RV20:
185
      {
186 187 188 189
        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
190 191
            "systemstream", G_TYPE_BOOLEAN, FALSE,
            "rmversion", G_TYPE_INT, version, NULL);
192 193 194 195
        if (context) {
          gst_caps_set_simple (caps,
              "rmsubid", GST_TYPE_FOURCC, context->sub_id, NULL);
        }
196
      }
197
      break;
198

199
    case CODEC_ID_MP2:
200 201 202 203
      /* 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
204
            "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 2, NULL);
205
      }
206
      break;
207

208 209 210 211
    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
212
            "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 3, NULL);
213 214 215 216
      } 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
217 218
            "mpegversion", G_TYPE_INT, 1,
            "layer", GST_TYPE_INT_RANGE, 1, 3, NULL);
219
      }
220
      break;
221

David Schleef's avatar
David Schleef committed
222
    case CODEC_ID_VORBIS:
223 224 225 226 227 228 229
      /* 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.
       */
230
      break;
231

232
    case CODEC_ID_AC3:
233 234 235 236 237 238
      /* 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 */
239
        caps = GST_FF_AUD_CAPS_NEW ("audio/x-ac3", NULL);
240
      }
241
      break;
242

Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
243 244 245 246 247
      /* 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...)? */
248
    case CODEC_ID_MJPEG:
249 250
    case CODEC_ID_LJPEG:
    case CODEC_ID_SP5X:
251
      caps = GST_FF_VID_CAPS_NEW ("image/jpeg", NULL);
Wim Taymans's avatar
Wim Taymans committed
252
      break;
253

254 255 256 257
    case CODEC_ID_MJPEGB:
      caps = GST_FF_VID_CAPS_NEW ("video/x-mjpeg-b", NULL);
      break;

258
    case CODEC_ID_MPEG4:
259
      if (encode && context != NULL) {
260 261
        /* I'm not exactly sure what ffmpeg outputs... ffmpeg itself uses
         * the AVI fourcc 'DIVX', but 'mp4v' for Quicktime... */
262
        switch (context->codec_tag) {
263 264 265 266 267 268 269 270 271 272 273 274
          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;
        }
275 276 277
      } 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
278 279
            "mpegversion", G_TYPE_INT, 4,
            "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
280 281 282 283 284 285 286 287 288
        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));
        }
289
      }
290
      break;
291

292
    case CODEC_ID_RAWVIDEO:
293
      caps = gst_ffmpeg_codectype_to_caps (CODEC_TYPE_VIDEO, context);
294
      break;
295

296
    case CODEC_ID_MSMPEG4V1:
297 298
    case CODEC_ID_MSMPEG4V2:
    case CODEC_ID_MSMPEG4V3:
299
      {
300 301 302 303
        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
304
            "msmpegversion", G_TYPE_INT, version, NULL);
305 306
        if (!encode && codec_id == CODEC_ID_MSMPEG4V3) {
          gst_caps_append (caps, GST_FF_VID_CAPS_NEW ("video/x-divx",
307
              "divxversion", G_TYPE_INT, 3, NULL));
308
        }
309
      }
310
      break;
311

312
    case CODEC_ID_WMV1:
313
    case CODEC_ID_WMV2:
314
      {
315 316
        gint version = (codec_id == CODEC_ID_WMV1) ? 1 : 2;

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

322 323
    case CODEC_ID_FLV1:
      buildcaps = TRUE;
324
      break;
325

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

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

336
    case CODEC_ID_DVAUDIO:
337
      caps = GST_FF_AUD_CAPS_NEW ("audio/x-dv", NULL);
338
      break;
339

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

346 347
    case CODEC_ID_WMAV1:
    case CODEC_ID_WMAV2:
348
      {
349 350
        gint version = (codec_id == CODEC_ID_WMAV1) ? 1 : 2;

351
        if (context) {
352 353 354 355
          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);
356
        } else {
357 358 359 360 361
          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);
        }
362
      }
363
      break;
364

365 366
    case CODEC_ID_MACE3:
    case CODEC_ID_MACE6:
367
      {
368 369 370
        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
371
            "maceversion", G_TYPE_INT, version, NULL);
372
      }
373
      break;
374

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

    case CODEC_ID_CYUV:
384
      buildcaps = TRUE;
385 386 387
      break;

    case CODEC_ID_H264:
388
      caps = GST_FF_VID_CAPS_NEW ("video/x-h264", NULL);
389 390 391
      break;

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

396 397 398 399 400
    case CODEC_ID_INDEO2:
      caps = GST_FF_VID_CAPS_NEW ("video/x-indeo",
          "indeoversion", G_TYPE_INT, 2, NULL);
      break;

401
    case CODEC_ID_VP3:
402
      caps = GST_FF_VID_CAPS_NEW ("video/x-vp3", NULL);
403 404
      break;

405
    case CODEC_ID_THEORA:
406
      caps = GST_FF_VID_CAPS_NEW ("video/x-theora", NULL);
407 408
      break;

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

    case CODEC_ID_ASV1:
416 417
    case CODEC_ID_ASV2:
      buildcaps = TRUE;
418 419
      break;

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

    case CODEC_ID_4XM:
426
      caps = GST_FF_VID_CAPS_NEW ("video/x-4xm", NULL);
427 428
      break;

429 430 431 432 433 434
    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;

435
    case CODEC_ID_FRAPS:
436 437 438 439 440 441 442 443
    case CODEC_ID_VCR1:
    case CODEC_ID_CLJR:
    case CODEC_ID_MDEC:
    case CODEC_ID_ROQ:
    case CODEC_ID_INTERPLAY_VIDEO:
      buildcaps = TRUE;
      break;

444 445 446 447
    case CODEC_ID_RPZA:
      caps = GST_FF_VID_CAPS_NEW ("video/x-apple-video", NULL);
      break;

448
    case CODEC_ID_CINEPAK:
449
      caps = GST_FF_VID_CAPS_NEW ("video/x-cinepak", NULL);
450 451
      break;

452 453 454 455 456 457 458 459 460 461 462 463 464
    /* 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;

465 466 467 468 469 470 471 472 473 474 475
    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;

476 477 478 479 480
    case CODEC_ID_MSVIDEO1:
      caps = GST_FF_VID_CAPS_NEW ("video/x-msvideocodec",
	  "msvideoversion", G_TYPE_INT, 1, NULL);
      break;

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

490 491 492 493 494 495
    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:
496
    case CODEC_ID_TRUEMOTION2:
497 498 499 500
    case CODEC_ID_VMDVIDEO:
    case CODEC_ID_VMDAUDIO:
    case CODEC_ID_MSZH:
    case CODEC_ID_ZLIB:
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
    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:
517 518 519 520 521 522
    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:
523 524 525
      buildcaps = TRUE;
      break;

Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
526
      /* weird quasi-codecs for the demuxers only */
527 528 529 530 531 532
    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:
533
      {
534
        gint width = 0, depth = 0, endianness = 0;
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
535
        gboolean signedness = FALSE;    /* blabla */
536 537 538

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

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

587
    case CODEC_ID_PCM_MULAW:
588
      caps = GST_FF_AUD_CAPS_NEW ("audio/x-mulaw", NULL);
589 590 591
      break;

    case CODEC_ID_PCM_ALAW:
592
      caps = GST_FF_AUD_CAPS_NEW ("audio/x-alaw", NULL);
593 594
      break;

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

        switch (codec_id) {
          case CODEC_ID_ADPCM_IMA_QT:
            layout = "quicktime";
            break;
          case CODEC_ID_ADPCM_IMA_WAV:
618
            layout = "dvi";
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 647 648 649
            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;
650 651 652
          case CODEC_ID_ADPCM_CT:
            layout = "ct";
            break;
653 654 655
          case CODEC_ID_ADPCM_SWF:
            layout = "swf";
            break;
656 657 658
          case CODEC_ID_ADPCM_YAMAHA:
            layout = "yamaha";
            break;
659
          default:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
660
            g_assert (0);       /* don't worry, we never get here */
661 662 663 664 665 666
            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
667
            "layout", G_TYPE_STRING, layout, NULL);
668 669 670 671
        if (context)
          gst_caps_set_simple (caps,
              "block_align", G_TYPE_INT, context->block_align,
              "bitrate", G_TYPE_INT, context->bit_rate, NULL);
672
      }
673 674 675
      break;

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

679
    case CODEC_ID_AMR_WB:
680
      caps = GST_FF_AUD_CAPS_NEW ("audio/x-amr-wb", NULL);
681 682
      break;

683
    case CODEC_ID_RA_144:
684
    case CODEC_ID_RA_288:
685
      {
686 687 688 689
        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
690
            "raversion", G_TYPE_INT, version, NULL);
691
      }
692
      break;
693

694 695 696
    case CODEC_ID_ROQ_DPCM:
    case CODEC_ID_INTERPLAY_DPCM:
    case CODEC_ID_XAN_DPCM:
697
    case CODEC_ID_SOL_DPCM:
698
      {
699 700 701 702 703 704 705 706 707 708 709 710
        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;
711 712 713
          case CODEC_ID_SOL_DPCM:
            layout = "sol";
            break;
714
          default:
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
715
            g_assert (0);       /* don't worry, we never get here */
716 717 718 719 720 721
            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
722
            "layout", G_TYPE_STRING, layout, NULL);
723 724 725 726
        if (context)
          gst_caps_set_simple (caps,
              "block_align", G_TYPE_INT, context->block_align,
              "bitrate", G_TYPE_INT, context->bit_rate, NULL);
727
      }
728
      break;
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
729

730 731 732 733 734 735 736 737 738 739 740 741
    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;

742 743 744 745 746 747
    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);
      }
748 749
      break;

750 751 752 753 754
    case CODEC_ID_DVD_SUBTITLE:
    case CODEC_ID_DVB_SUBTITLE:
      caps = NULL;
      break;

755
    default:
756
      g_warning ("Unknown codec ID %d, please add here", codec_id);
757 758 759
      break;
  }

760 761 762 763 764 765 766 767 768 769
  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);
770
          caps = GST_FF_VID_CAPS_NEW (mime, NULL);
771 772 773 774
          g_free (mime);
          break;
        case CODEC_TYPE_AUDIO:
          mime = g_strdup_printf ("audio/x-gst_ff-%s", codec->name);
775
          caps = GST_FF_AUD_CAPS_NEW (mime, NULL);
776
          if (context)
777 778 779
            gst_caps_set_simple (caps,
                "block_align", G_TYPE_INT, context->block_align,
                "bitrate", G_TYPE_INT, context->bit_rate, NULL);
780 781 782 783 784 785 786 787
          g_free (mime);
          break;
        default:
          break;
      }
    }
  }

788
  if (caps != NULL) {
789 790 791 792

    /* 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
793

794 795 796 797 798 799 800
      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);
    }

801 802 803 804 805
    /* palette */
    if (context) {
      gst_ffmpeg_set_palette (caps, context);
    }

806
    GST_DEBUG ("caps for codec_id=%d: %" GST_PTR_FORMAT, codec_id, caps);
807

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

  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
823
gst_ffmpeg_pixfmt_to_caps (enum PixelFormat pix_fmt, AVCodecContext * context)
824 825 826 827
{
  GstCaps *caps = NULL;

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

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

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

  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
961 962
gst_ffmpeg_smpfmt_to_caps (enum SampleFormat sample_fmt,
    AVCodecContext * context)
963 964 965 966 967 968 969 970 971 972
{
  GstCaps *caps = NULL;

  int bpp = 0;
  gboolean signedness = FALSE;

  switch (sample_fmt) {
    case SAMPLE_FMT_S16:
      signedness = TRUE;
      bpp = 16;
973
      break;
974

975
    default:
976
      /* .. */
977 978 979
      break;
  }

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

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

David Schleef's avatar
David Schleef committed
990
    GST_DEBUG ("caps for sample_fmt=%d: %s", sample_fmt, str);
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
991
    g_free (str);
992
  } else {
David Schleef's avatar
David Schleef committed
993
    GST_WARNING ("No caps found for sample_fmt=%d", sample_fmt);