gstffmpegcodecmap.c 97.8 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
#ifdef HAVE_FFMPEG_UNINSTALLED
#include <avcodec.h>
#else
29
#include <libavcodec/avcodec.h>
30
#endif
31
#include <string.h>
32

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

Wim Taymans's avatar
Wim Taymans committed
36
#include <gst/video/video.h>
Wim Taymans's avatar
Wim Taymans committed
37
#include <gst/audio/audio.h>
38 39
#include <gst/pbutils/codec-utils.h>

40 41 42 43 44
/*
 * Read a palette from a caps.
 */

static void
45
gst_ffmpeg_get_palette (const GstCaps * caps, AVCodecContext * context)
46 47 48
{
  GstStructure *str = gst_caps_get_structure (caps, 0);
  const GValue *palette_v;
Wim Taymans's avatar
Wim Taymans committed
49
  GstBuffer *palette;
50 51

  /* do we have a palette? */
52
  if ((palette_v = gst_structure_get_value (str, "palette_data")) && context) {
53
    palette = gst_value_get_buffer (palette_v);
Wim Taymans's avatar
Wim Taymans committed
54
    if (gst_buffer_get_size (palette) >= AVPALETTE_SIZE) {
55 56 57 58
      if (context->palctrl)
        av_free (context->palctrl);
      context->palctrl = av_malloc (sizeof (AVPaletteControl));
      context->palctrl->palette_changed = 1;
Wim Taymans's avatar
Wim Taymans committed
59
      gst_buffer_extract (palette, 0, context->palctrl->palette,
60 61 62 63 64 65
          AVPALETTE_SIZE);
    }
  }
}

static void
66
gst_ffmpeg_set_palette (GstCaps * caps, AVCodecContext * context)
67 68
{
  if (context->palctrl) {
69
    GstBuffer *palette = gst_buffer_new_and_alloc (AVPALETTE_SIZE);
70

Wim Taymans's avatar
Wim Taymans committed
71
    gst_buffer_fill (palette, 0, context->palctrl->palette, AVPALETTE_SIZE);
72
    gst_caps_set_simple (caps, "palette_data", GST_TYPE_BUFFER, palette, NULL);
73 74 75
  }
}

76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
/* IMPORTANT: Keep this sorted by the ffmpeg channel masks */
static const struct
{
  guint64 ff;
  GstAudioChannelPosition gst;
} _ff_to_gst_layout[] = {
  {
  CH_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, {
  CH_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {
  CH_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, {
  CH_LOW_FREQUENCY, GST_AUDIO_CHANNEL_POSITION_LFE}, {
  CH_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT}, {
  CH_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
  CH_FRONT_LEFT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, {
  CH_FRONT_RIGHT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, {
  CH_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, {
  CH_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT}, {
  CH_SIDE_RIGHT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}, {
  CH_TOP_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, {
  CH_TOP_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
  CH_TOP_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, {
  CH_TOP_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
  CH_TOP_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
  CH_TOP_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, {
  CH_TOP_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
  CH_STEREO_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, {
  CH_STEREO_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}
};

static GstAudioChannelPosition *
gst_ff_channel_layout_to_gst (guint64 channel_layout, guint channels)
{
  guint nchannels = 0, i, j;
  GstAudioChannelPosition *pos = NULL;
  gboolean none_layout = FALSE;

  for (i = 0; i < 64; i++) {
    if ((channel_layout & (G_GUINT64_CONSTANT (1) << i)) != 0) {
      nchannels++;
    }
  }

  if (channel_layout == 0) {
    nchannels = channels;
    none_layout = TRUE;
  }

  if (nchannels != channels) {
    GST_ERROR ("Number of channels is different (%u != %u)", channels,
        nchannels);
    return NULL;
  }

  pos = g_new (GstAudioChannelPosition, nchannels);

  for (i = 0, j = 0; i < G_N_ELEMENTS (_ff_to_gst_layout); i++) {
    if ((channel_layout & _ff_to_gst_layout[i].ff) != 0) {
      pos[j++] = _ff_to_gst_layout[i].gst;

      if (_ff_to_gst_layout[i].gst == GST_AUDIO_CHANNEL_POSITION_NONE)
        none_layout = TRUE;
    }
  }

  if (j != nchannels) {
    GST_WARNING ("Unknown channels in channel layout - assuming NONE layout");
    none_layout = TRUE;
  }

145 146 147
  if (!none_layout && !gst_audio_check_channel_positions (pos, nchannels)) {
    GST_ERROR ("Invalid channel layout %" G_GUINT64_FORMAT
        " - assuming NONE layout", channel_layout);
148 149 150 151 152 153 154 155 156
    none_layout = TRUE;
  }

  if (none_layout) {
    if (nchannels == 1) {
      pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO;
    } else if (nchannels == 2) {
      pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
      pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
157 158 159
    } else if (channel_layout == 0) {
      g_free (pos);
      pos = NULL;
160 161 162 163 164 165
    } else {
      for (i = 0; i < nchannels; i++)
        pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
    }
  }

166 167 168 169 170 171 172 173 174 175
  if (nchannels == 1 && pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER) {
    GST_DEBUG ("mono common case; won't set channel positions");
    g_free (pos);
    pos = NULL;
  } else if (nchannels == 2 && pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT
      && pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT) {
    GST_DEBUG ("stereo common case; won't set channel positions");
    g_free (pos);
    pos = NULL;
  }
176 177 178 179

  return pos;
}

180 181 182 183
/* 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.
184 185 186
 *
 * We should actually do this stuff at the end, like in riff-media.c,
 * but I'm too lazy today. Maybe later.
187
 */
188
static GstCaps *
189 190
gst_ff_vid_caps_new (AVCodecContext * context, enum CodecID codec_id,
    const char *mimetype, const char *fieldname, ...)
191 192 193 194
{
  GstStructure *structure = NULL;
  GstCaps *caps = NULL;
  va_list var_args;
195
  gint i;
196

197 198
  GST_LOG ("context:%p, codec_id:%d, mimetype:%s", context, codec_id, mimetype);

199 200
  /* fixed, non probing context */
  if (context != NULL && context->width != -1) {
201 202
    gint num, denom;

203 204
    caps = gst_caps_new_simple (mimetype,
        "width", G_TYPE_INT, context->width,
205 206 207 208 209
        "height", G_TYPE_INT, context->height, NULL);

    num = context->time_base.den / context->ticks_per_frame;
    denom = context->time_base.num;

210 211 212 213
    if (!denom) {
      GST_LOG ("invalid framerate: %d/0, -> %d/1", num, num);
      denom = 1;
    }
214 215 216 217 218 219 220 221
    if (gst_util_fraction_compare (num, denom, 1000, 1) > 0) {
      GST_LOG ("excessive framerate: %d/%d, -> 0/1", num, denom);
      num = 0;
      denom = 1;
    }
    GST_LOG ("setting framerate: %d/%d", num, denom);
    gst_caps_set_simple (caps,
        "framerate", GST_TYPE_FRACTION, num, denom, NULL);
222
  } else {
223
    /* so we are after restricted caps in this case */
224
    switch (codec_id) {
225 226 227 228 229 230 231 232 233 234 235 236
      case CODEC_ID_H261:
      {
        caps = gst_caps_new_simple (mimetype,
            "width", G_TYPE_INT, 352,
            "height", G_TYPE_INT, 288,
            "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
        gst_caps_append (caps, gst_caps_new_simple (mimetype,
                "width", G_TYPE_INT, 176,
                "height", G_TYPE_INT, 144,
                "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL));
        break;
      }
237 238 239 240 241 242 243 244 245
      case CODEC_ID_H263:
      {
        /* 128x96, 176x144, 352x288, 704x576, and 1408x1152. slightly reordered
         * because we want automatic negotiation to go as close to 320x240 as
         * possible. */
        const static gint widths[] = { 352, 704, 176, 1408, 128 };
        const static gint heights[] = { 288, 576, 144, 1152, 96 };
        GstCaps *temp;
        gint n_sizes = G_N_ELEMENTS (widths);
246

247 248 249 250 251 252
        caps = gst_caps_new_empty ();
        for (i = 0; i < n_sizes; i++) {
          temp = gst_caps_new_simple (mimetype,
              "width", G_TYPE_INT, widths[i],
              "height", G_TYPE_INT, heights[i],
              "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
253

254 255 256 257
          gst_caps_append (caps, temp);
        }
        break;
      }
258 259
      case CODEC_ID_DVVIDEO:
      {
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
        static struct
        {
          guint32 csp;
          gint width, height;
          gint par_n, par_d;
          gint framerate_n, framerate_d;
        } profiles[] = {
          {
          GST_MAKE_FOURCC ('Y', '4', '1', 'B'), 720, 480, 10, 11, 30000, 1001}, {
          GST_MAKE_FOURCC ('Y', '4', '1', 'B'), 720, 480, 40, 33, 30000, 1001}, {
          GST_MAKE_FOURCC ('I', '4', '2', '0'), 720, 576, 59, 54, 25, 1}, {
          GST_MAKE_FOURCC ('I', '4', '2', '0'), 720, 576, 118, 81, 25, 1}, {
          GST_MAKE_FOURCC ('Y', '4', '1', 'B'), 720, 576, 59, 54, 25, 1}, {
          GST_MAKE_FOURCC ('Y', '4', '1', 'B'), 720, 576, 118, 81, 25, 1}
        };
275
        GstCaps *temp;
276
        gint n_sizes = G_N_ELEMENTS (profiles);
277 278 279 280

        caps = gst_caps_new_empty ();
        for (i = 0; i < n_sizes; i++) {
          temp = gst_caps_new_simple (mimetype,
281 282 283 284 285
              "width", G_TYPE_INT, profiles[i].width,
              "height", G_TYPE_INT, profiles[i].height,
              "framerate", GST_TYPE_FRACTION, profiles[i].framerate_n,
              profiles[i].framerate_d, "pixel-aspect-ratio", GST_TYPE_FRACTION,
              profiles[i].par_n, profiles[i].par_d, NULL);
286 287

          gst_caps_append (caps, temp);
288
        }
289 290
        break;
      }
291 292
      case CODEC_ID_DNXHD:
      {
293
        caps = gst_caps_new_simple (mimetype,
294 295
            "width", G_TYPE_INT, 1920,
            "height", G_TYPE_INT, 1080,
296
            "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
297 298 299 300 301 302 303
        gst_caps_append (caps, gst_caps_new_simple (mimetype,
                "width", G_TYPE_INT, 1280,
                "height", G_TYPE_INT, 720,
                "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL));
        break;
      }
      default:
304 305 306 307
        break;
    }
  }

308 309
  /* no fixed caps or special restrictions applied;
   * default unfixed setting */
310 311
  if (!caps) {
    GST_DEBUG ("Creating default caps");
312 313 314 315
    caps = gst_caps_new_simple (mimetype,
        "width", GST_TYPE_INT_RANGE, 16, 4096,
        "height", GST_TYPE_INT_RANGE, 16, 4096,
        "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
316
  }
317

318
  for (i = 0; i < gst_caps_get_size (caps); i++) {
319
    va_start (var_args, fieldname);
320
    structure = gst_caps_get_structure (caps, i);
321 322 323 324 325 326
    gst_structure_set_valist (structure, fieldname, var_args);
    va_end (var_args);
  }

  return caps;
}
327 328 329

/* same for audio - now with channels/sample rate
 */
330
static GstCaps *
331 332
gst_ff_aud_caps_new (AVCodecContext * context, enum CodecID codec_id,
    const char *mimetype, const char *fieldname, ...)
333 334 335
{
  GstCaps *caps = NULL;
  GstStructure *structure = NULL;
336
  gint i;
337 338
  va_list var_args;

339 340
  /* fixed, non-probing context */
  if (context != NULL && context->channels != -1) {
341
    GstAudioChannelPosition *pos;
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
    guint64 channel_layout = context->channel_layout;

    if (channel_layout == 0) {
      const guint64 default_channel_set[] = {
        0, 0, CH_LAYOUT_SURROUND, CH_LAYOUT_QUAD, CH_LAYOUT_5POINT0,
        CH_LAYOUT_5POINT1, 0, CH_LAYOUT_7POINT1
      };

      switch (codec_id) {
        case CODEC_ID_EAC3:
        case CODEC_ID_AC3:
        case CODEC_ID_DTS:
          if (context->channels > 0
              && context->channels < G_N_ELEMENTS (default_channel_set))
            channel_layout = default_channel_set[context->channels - 1];
          break;
        default:
          break;
      }
    }
362

363 364
    caps = gst_caps_new_simple (mimetype,
        "rate", G_TYPE_INT, context->sample_rate,
365
        "channels", G_TYPE_INT, context->channels, NULL);
366

367
    pos = gst_ff_channel_layout_to_gst (channel_layout, context->channels);
368 369 370 371
    if (pos != NULL) {
      gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos);
      g_free (pos);
    }
372
  } else {
373 374 375
    gint maxchannels = 2;
    const gint *rates = NULL;
    gint n_rates = 0;
376

377
    /* so we must be after restricted caps in this case */
378 379
    switch (codec_id) {
      case CODEC_ID_AAC:
380
      case CODEC_ID_AAC_LATM:
381 382 383
      case CODEC_ID_DTS:
        maxchannels = 6;
        break;
384 385 386 387 388 389 390
      case CODEC_ID_MP2:
      {
        const static gint l_rates[] =
            { 48000, 44100, 32000, 24000, 22050, 16000 };
        n_rates = G_N_ELEMENTS (l_rates);
        rates = l_rates;
        break;
391
      }
392 393 394 395 396 397 398 399 400 401
      case CODEC_ID_EAC3:
      case CODEC_ID_AC3:
      {
        const static gint l_rates[] = { 48000, 44100, 32000 };
        maxchannels = 6;
        n_rates = G_N_ELEMENTS (l_rates);
        rates = l_rates;
        break;
      }
      case CODEC_ID_ADPCM_G722:
402 403 404 405 406 407 408
      {
        const static gint l_rates[] = { 16000 };
        n_rates = G_N_ELEMENTS (l_rates);
        rates = l_rates;
        maxchannels = 1;
        break;
      }
409
      case CODEC_ID_ADPCM_G726:
410 411 412 413
      {
        const static gint l_rates[] = { 8000 };
        n_rates = G_N_ELEMENTS (l_rates);
        rates = l_rates;
414 415
        maxchannels = 1;
        break;
416
      }
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
      case CODEC_ID_ADPCM_SWF:
      {
        const static gint l_rates[] = { 11025, 22050, 44100 };
        n_rates = G_N_ELEMENTS (l_rates);
        rates = l_rates;
        break;
      }
      case CODEC_ID_ROQ_DPCM:
      {
        const static gint l_rates[] = { 22050 };
        n_rates = G_N_ELEMENTS (l_rates);
        rates = l_rates;
        break;
      }
      case CODEC_ID_AMR_NB:
      {
        const static gint l_rates[] = { 8000 };
        maxchannels = 1;
        n_rates = G_N_ELEMENTS (l_rates);
        rates = l_rates;
        break;
      }
      case CODEC_ID_AMR_WB:
      {
        const static gint l_rates[] = { 16000 };
        maxchannels = 1;
        n_rates = G_N_ELEMENTS (l_rates);
        rates = l_rates;
        break;
      }
      default:
        break;
449 450
    }

451 452 453 454
    /* TODO: handle context->channel_layouts here to set
     * the list of channel layouts supported by the encoder.
     * Unfortunately no encoder uses this yet....
     */
455 456 457 458
    /* regardless of encode/decode, open up channels if applicable */
    /* Until decoders/encoders expose the maximum number of channels
     * they support, we whitelist them here. */
    switch (codec_id) {
459 460 461 462
      case CODEC_ID_WMAPRO:
      case CODEC_ID_TRUEHD:
        maxchannels = 8;
        break;
463 464 465
      default:
        break;
    }
466

467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
    if (maxchannels == 1)
      caps = gst_caps_new_simple (mimetype,
          "channels", G_TYPE_INT, maxchannels, NULL);
    else
      caps = gst_caps_new_simple (mimetype,
          "channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL);
    if (n_rates) {
      GValue list = { 0, };
      GstStructure *structure;

      g_value_init (&list, GST_TYPE_LIST);
      for (i = 0; i < n_rates; i++) {
        GValue v = { 0, };

        g_value_init (&v, G_TYPE_INT);
        g_value_set_int (&v, rates[i]);
        gst_value_list_append_value (&list, &v);
        g_value_unset (&v);
      }
      structure = gst_caps_get_structure (caps, 0);
      gst_structure_set_value (structure, "rate", &list);
      g_value_unset (&list);
    } else
490
      gst_caps_set_simple (caps, "rate", GST_TYPE_INT_RANGE, 4000, 96000, NULL);
491 492
  }

493
  for (i = 0; i < gst_caps_get_size (caps); i++) {
494
    va_start (var_args, fieldname);
495
    structure = gst_caps_get_structure (caps, i);
496 497 498 499 500 501
    gst_structure_set_valist (structure, fieldname, var_args);
    va_end (var_args);
  }

  return caps;
}
502 503 504 505 506 507

/* 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!
508 509 510 511 512 513 514 515 516
 *
 * 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.
517 518
 */

519
GstCaps *
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
520 521
gst_ffmpeg_codecid_to_caps (enum CodecID codec_id,
    AVCodecContext * context, gboolean encode)
522
{
523
  GstCaps *caps = NULL;
524
  gboolean buildcaps = FALSE;
525

526 527
  GST_LOG ("codec_id:%d, context:%p, encode:%d", codec_id, context, encode);

528
  switch (codec_id) {
529
    case CODEC_ID_MPEG1VIDEO:
530 531 532 533
      /* FIXME: bitrate */
      caps = gst_ff_vid_caps_new (context, codec_id, "video/mpeg",
          "mpegversion", G_TYPE_INT, 1,
          "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
534 535 536 537 538
      break;

    case CODEC_ID_MPEG2VIDEO:
      if (encode) {
        /* FIXME: bitrate */
539
        caps = gst_ff_vid_caps_new (context, codec_id, "video/mpeg",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
540 541
            "mpegversion", G_TYPE_INT, 2,
            "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
542 543 544 545
      } 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
546 547
            "mpegversion", GST_TYPE_INT_RANGE, 1, 2,
            "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
548
      }
549
      break;
550 551 552 553 554 555

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

    case CODEC_ID_H263:
556
      if (encode) {
557
        caps = gst_ff_vid_caps_new (context, codec_id, "video/x-h263",
558 559 560
            "variant", G_TYPE_STRING, "itu",
            "h263version", G_TYPE_STRING, "h263", NULL);
      } else {
561 562 563 564
        /* don't pass codec_id, we can decode other variants with the H263
         * decoder that don't have specific size requirements
         */
        caps = gst_ff_vid_caps_new (context, CODEC_ID_NONE, "video/x-h263",
565 566
            "variant", G_TYPE_STRING, "itu", NULL);
      }
567 568 569
      break;

    case CODEC_ID_H263P:
570
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-h263",
571 572
          "variant", G_TYPE_STRING, "itu",
          "h263version", G_TYPE_STRING, "h263p", NULL);
573 574 575 576 577 578 579 580 581
      if (encode && context) {

        gst_caps_set_simple (caps,
            "annex-f", G_TYPE_BOOLEAN, context->flags & CODEC_FLAG_4MV,
            "annex-j", G_TYPE_BOOLEAN, context->flags & CODEC_FLAG_LOOP_FILTER,
            "annex-i", G_TYPE_BOOLEAN, context->flags & CODEC_FLAG_AC_PRED,
            "annex-t", G_TYPE_BOOLEAN, context->flags & CODEC_FLAG_AC_PRED,
            NULL);
      }
582
      break;
583

584
    case CODEC_ID_H263I:
585
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-intel-h263",
586
          "variant", G_TYPE_STRING, "intel", NULL);
587 588
      break;

589
    case CODEC_ID_H261:
590
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-h261", NULL);
591 592
      break;

593
    case CODEC_ID_RV10:
594
    case CODEC_ID_RV20:
595
    case CODEC_ID_RV30:
596
    case CODEC_ID_RV40:
597 598
    {
      gint version;
599

600 601 602 603
      switch (codec_id) {
        case CODEC_ID_RV40:
          version = 4;
          break;
604 605 606
        case CODEC_ID_RV30:
          version = 3;
          break;
607 608 609 610 611 612 613
        case CODEC_ID_RV20:
          version = 2;
          break;
        default:
          version = 1;
          break;
      }
614

615 616 617 618 619
      /* FIXME: context->sub_id must be filled in during decoding */
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-pn-realvideo",
          "systemstream", G_TYPE_BOOLEAN, FALSE,
          "rmversion", G_TYPE_INT, version, NULL);
      if (context) {
620
        gst_caps_set_simple (caps, "format", G_TYPE_INT, context->sub_id, NULL);
621 622
        if (context->extradata_size >= 8) {
          gst_caps_set_simple (caps,
623 624 625
              "subformat", G_TYPE_INT, GST_READ_UINT32_BE (context->extradata),
              NULL);
        }
626
      }
627
    }
628
      break;
629

630 631 632 633 634 635
    case CODEC_ID_MP1:
      /* FIXME: bitrate */
      caps = gst_ff_aud_caps_new (context, codec_id, "audio/mpeg",
          "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 1, NULL);
      break;

636
    case CODEC_ID_MP2:
637 638 639
      /* FIXME: bitrate */
      caps = gst_ff_aud_caps_new (context, codec_id, "audio/mpeg",
          "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 2, NULL);
640
      break;
641

642 643 644
    case CODEC_ID_MP3:
      if (encode) {
        /* FIXME: bitrate */
645
        caps = gst_ff_aud_caps_new (context, codec_id, "audio/mpeg",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
646
            "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 3, NULL);
647 648 649 650
      } 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
651 652
            "mpegversion", G_TYPE_INT, 1,
            "layer", GST_TYPE_INT_RANGE, 1, 3, NULL);
653
      }
654
      break;
655

656 657 658 659 660 661 662
    case CODEC_ID_MUSEPACK7:
      caps =
          gst_ff_aud_caps_new (context, codec_id,
          "audio/x-ffmpeg-parsed-musepack", "streamversion", G_TYPE_INT, 7,
          NULL);
      break;

663 664 665 666 667 668 669
    case CODEC_ID_MUSEPACK8:
      caps =
          gst_ff_aud_caps_new (context, codec_id,
          "audio/x-ffmpeg-parsed-musepack", "streamversion", G_TYPE_INT, 8,
          NULL);
      break;

670 671 672
    case CODEC_ID_AC3:
      /* FIXME: bitrate */
      caps = gst_ff_aud_caps_new (context, codec_id, "audio/x-ac3", NULL);
673
      break;
674

675 676 677 678 679
    case CODEC_ID_EAC3:
      /* FIXME: bitrate */
      caps = gst_ff_aud_caps_new (context, codec_id, "audio/x-eac3", NULL);
      break;

680 681 682 683 684
    case CODEC_ID_TRUEHD:
      caps = gst_ff_aud_caps_new (context, codec_id, "audio/x-true-hd", NULL);
      break;

    case CODEC_ID_ATRAC1:
685
      caps =
686
          gst_ff_aud_caps_new (context, codec_id, "audio/x-vnd.sony.atrac1",
687
          NULL);
688
      break;
689

690 691
    case CODEC_ID_ATRAC3:
      caps =
692
          gst_ff_aud_caps_new (context, codec_id, "audio/x-vnd.sony.atrac3",
693 694 695
          NULL);
      break;

696
    case CODEC_ID_DTS:
697
      caps = gst_ff_aud_caps_new (context, codec_id, "audio/x-dts", NULL);
698
      break;
699

700 701 702 703 704 705
    case CODEC_ID_APE:
      caps =
          gst_ff_aud_caps_new (context, codec_id, "audio/x-ffmpeg-parsed-ape",
          NULL);
      if (context) {
        gst_caps_set_simple (caps,
706
            "depth", G_TYPE_INT, context->bits_per_coded_sample, NULL);
707 708 709
      }
      break;

710 711 712
    case CODEC_ID_MLP:
      caps = gst_ff_aud_caps_new (context, codec_id, "audio/x-mlp", NULL);
      break;
713

714 715 716
    case CODEC_ID_IMC:
      caps = gst_ff_aud_caps_new (context, codec_id, "audio/x-imc", NULL);
      break;
717

Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
718 719 720 721 722
      /* 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...)? */
723
    case CODEC_ID_MJPEG:
724
    case CODEC_ID_LJPEG:
725
      caps = gst_ff_vid_caps_new (context, codec_id, "image/jpeg", NULL);
Wim Taymans's avatar
Wim Taymans committed
726
      break;
727

728
    case CODEC_ID_SP5X:
729
      caps = gst_ff_vid_caps_new (context, codec_id, "video/sp5x", NULL);
730 731
      break;

732
    case CODEC_ID_MJPEGB:
733
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-mjpeg-b", NULL);
734 735
      break;

736
    case CODEC_ID_MPEG4:
737
      if (encode && context != NULL) {
738 739
        /* I'm not exactly sure what ffmpeg outputs... ffmpeg itself uses
         * the AVI fourcc 'DIVX', but 'mp4v' for Quicktime... */
740
        switch (context->codec_tag) {
741
          case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
742
            caps = gst_ff_vid_caps_new (context, codec_id, "video/x-divx",
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
743
                "divxversion", G_TYPE_INT, 5, NULL);
744 745 746 747
            break;
          case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
          default:
            /* FIXME: bitrate */
748
            caps = gst_ff_vid_caps_new (context, codec_id, "video/mpeg",
749 750 751 752
                "systemstream", G_TYPE_BOOLEAN, FALSE,
                "mpegversion", G_TYPE_INT, 4, NULL);
            break;
        }
753 754
      } else {
        /* The trick here is to separate xvid, divx, mpeg4, 3ivx et al */
755
        caps = gst_ff_vid_caps_new (context, codec_id, "video/mpeg",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
756 757
            "mpegversion", G_TYPE_INT, 4,
            "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
758
        if (encode) {
759 760
          gst_caps_append (caps, gst_ff_vid_caps_new (context, codec_id,
                  "video/x-divx", "divxversion", G_TYPE_INT, 5, NULL));
761
        } else {
762 763 764 765 766 767 768
          gst_caps_append (caps, gst_ff_vid_caps_new (context, codec_id,
                  "video/x-divx", "divxversion", GST_TYPE_INT_RANGE, 4, 5,
                  NULL));
          gst_caps_append (caps, gst_ff_vid_caps_new (context, codec_id,
                  "video/x-xvid", NULL));
          gst_caps_append (caps, gst_ff_vid_caps_new (context, codec_id,
                  "video/x-3ivx", NULL));
769
        }
770
      }
771
      break;
772

773
    case CODEC_ID_RAWVIDEO:
774 775
      caps =
          gst_ffmpeg_codectype_to_caps (AVMEDIA_TYPE_VIDEO, context, codec_id,
776
          encode);
777
      break;
778

779
    case CODEC_ID_MSMPEG4V1:
780 781
    case CODEC_ID_MSMPEG4V2:
    case CODEC_ID_MSMPEG4V3:
782 783 784 785 786 787 788 789 790
    {
      gint version = 41 + codec_id - CODEC_ID_MSMPEG4V1;

      /* encode-FIXME: bitrate */
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-msmpeg",
          "msmpegversion", G_TYPE_INT, version, NULL);
      if (!encode && codec_id == CODEC_ID_MSMPEG4V3) {
        gst_caps_append (caps, gst_ff_vid_caps_new (context, codec_id,
                "video/x-divx", "divxversion", G_TYPE_INT, 3, NULL));
791
      }
792
    }
793
      break;
794

795
    case CODEC_ID_WMV1:
796
    case CODEC_ID_WMV2:
797 798
    {
      gint version = (codec_id == CODEC_ID_WMV1) ? 1 : 2;
799

800 801 802
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-wmv",
          "wmvversion", G_TYPE_INT, version, NULL);
    }
803
      break;
804

805
    case CODEC_ID_FLV1:
806 807
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-flash-video",
          "flvversion", G_TYPE_INT, 1, NULL);
808
      break;
809

810
    case CODEC_ID_SVQ1:
811
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-svq",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
812
          "svqversion", G_TYPE_INT, 1, NULL);
813
      break;
814 815

    case CODEC_ID_SVQ3:
816
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-svq",
817
          "svqversion", G_TYPE_INT, 3, NULL);
818
      break;
819

820
    case CODEC_ID_DVAUDIO:
821
      caps = gst_ff_aud_caps_new (context, codec_id, "audio/x-dv", NULL);
822
      break;
823

824
    case CODEC_ID_DVVIDEO:
825 826
    {
      if (encode && context) {
Wim Taymans's avatar
Wim Taymans committed
827
        const gchar *format;
828 829

        switch (context->pix_fmt) {
830
          case PIX_FMT_YUYV422:
Wim Taymans's avatar
Wim Taymans committed
831
            format = "YUY2";
832 833
            break;
          case PIX_FMT_YUV420P:
Wim Taymans's avatar
Wim Taymans committed
834
            format = "I420";
835
            break;
836
          case PIX_FMT_YUVA420P:
Wim Taymans's avatar
Wim Taymans committed
837
            format = "A420";
838
            break;
839
          case PIX_FMT_YUV411P:
Wim Taymans's avatar
Wim Taymans committed
840
            format = "Y41B";
841 842
            break;
          case PIX_FMT_YUV422P:
Wim Taymans's avatar
Wim Taymans committed
843
            format = "Y42B";
844 845
            break;
          case PIX_FMT_YUV410P:
Wim Taymans's avatar
Wim Taymans committed
846
            format = "YUV9";
847 848 849
            break;
          default:
            GST_WARNING
Wim Taymans's avatar
Wim Taymans committed
850
                ("Couldnt' find format for pixfmt %d, defaulting to I420",
851
                context->pix_fmt);
Wim Taymans's avatar
Wim Taymans committed
852
            format = "I420";
853 854 855 856
            break;
        }
        caps = gst_ff_vid_caps_new (context, codec_id, "video/x-dv",
            "systemstream", G_TYPE_BOOLEAN, FALSE,
Wim Taymans's avatar
Wim Taymans committed
857
            "format", G_TYPE_STRING, format, NULL);
858 859 860
      } else {
        caps = gst_ff_vid_caps_new (context, codec_id, "video/x-dv",
            "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
861
      }
862
    }
863
      break;
864

865 866
    case CODEC_ID_WMAV1:
    case CODEC_ID_WMAV2:
867 868
    {
      gint version = (codec_id == CODEC_ID_WMAV1) ? 1 : 2;
869

870 871 872 873 874 875 876 877 878 879
      if (context) {
        caps = gst_ff_aud_caps_new (context, codec_id, "audio/x-wma",
            "wmaversion", G_TYPE_INT, version,
            "block_align", G_TYPE_INT, context->block_align,
            "bitrate", G_TYPE_INT, context->bit_rate, NULL);
      } else {
        caps = gst_ff_aud_caps_new (context, codec_id, "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);
880
      }
881
    }
882
      break;
883 884 885 886 887 888
    case CODEC_ID_WMAPRO:
    {
      caps = gst_ff_aud_caps_new (context, codec_id, "audio/x-wma",
          "wmaversion", G_TYPE_INT, 3, NULL);
      break;
    }
889

890 891 892 893 894 895
    case CODEC_ID_WMAVOICE:
    {
      caps = gst_ff_aud_caps_new (context, codec_id, "audio/x-wms", NULL);
      break;
    }

896 897
    case CODEC_ID_MACE3:
    case CODEC_ID_MACE6:
898 899
    {
      gint version = (codec_id == CODEC_ID_MACE3) ? 3 : 6;
900

901 902 903
      caps = gst_ff_aud_caps_new (context, codec_id, "audio/x-mace",
          "maceversion", G_TYPE_INT, version, NULL);
    }
904
      break;
905

Wim Taymans's avatar
Wim Taymans committed
906
    case CODEC_ID_HUFFYUV:
907
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-huffyuv", NULL);
908 909
      if (context) {
        gst_caps_set_simple (caps,
910
            "bpp", G_TYPE_INT, context->bits_per_coded_sample, NULL);
911
      }
912 913 914
      break;

    case CODEC_ID_CYUV:
915 916 917
      caps =
          gst_ff_vid_caps_new (context, codec_id, "video/x-compressed-yuv",
          NULL);
918 919 920
      break;

    case CODEC_ID_H264:
921
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-h264", NULL);
922 923
      break;

924 925 926 927 928
    case CODEC_ID_INDEO5:
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-indeo",
          "indeoversion", G_TYPE_INT, 5, NULL);
      break;

929
    case CODEC_ID_INDEO3:
930
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-indeo",
Thomas Vander Stichele's avatar
indent  
Thomas Vander Stichele committed
931
          "indeoversion", G_TYPE_INT, 3, NULL);
932 933
      break;

934
    case CODEC_ID_INDEO2:
935
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-indeo",
936 937 938
          "indeoversion", G_TYPE_INT, 2, NULL);
      break;

939
    case CODEC_ID_FLASHSV:
940 941
      caps =
          gst_ff_vid_caps_new (context, codec_id, "video/x-flash-screen", NULL);
942 943
      break;

944
    case CODEC_ID_VP3:
945
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-vp3", NULL);
946 947
      break;

948
    case CODEC_ID_VP5:
949
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-vp5", NULL);
950 951 952
      break;

    case CODEC_ID_VP6:
953
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-vp6", NULL);
954 955 956
      break;

    case CODEC_ID_VP6F:
957
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-vp6-flash", NULL);
958 959
      break;

960 961 962 963
    case CODEC_ID_VP6A:
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-vp6-alpha", NULL);
      break;

964 965 966 967
    case CODEC_ID_VP8:
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-vp8", NULL);
      break;

968
    case CODEC_ID_THEORA:
969
      caps = gst_ff_vid_caps_new (context, codec_id, "video/x-theora", NULL);
970 971
      break;

972
    case CODEC_ID_AAC:
973
    {
974
      caps = gst_ff_aud_caps_new (context, codec_id, "audio/mpeg", NULL);
975 976 977 978 979

      if (!encode) {
        GValue arr = { 0, };
        GValue item = { 0, };

980 981 982 983 984 985 986 987 988 989 990
        g_value_init (&arr, GST_TYPE_LIST);
        g_value_init (&item, G_TYPE_INT);
        g_value_set_int (&item, 2);
        gst_value_list_append_value (&arr, &item);
        g_value_set_int (&item, 4);
        gst_value_list_append_value (&arr, &item);
        g_value_unset (&item);

        gst_caps_set_value (caps, "mpegversion", &arr);
        g_value_unset (&arr);