ext/ffmpeg/: Add some more width/height/channels/rate limitations to caps to cater...
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Wed, 8 Oct 2008 14:20:37 +0000 (14:20 +0000)
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Wed, 8 Oct 2008 14:20:37 +0000 (14:20 +0000)
Original commit message from CVS:
* ext/ffmpeg/gstffmpegcodecmap.c: (gst_ff_vid_caps_new),
(gst_ff_aud_caps_new), (gst_ffmpeg_codecid_to_caps),
(gst_ffmpeg_codectype_to_caps):
* ext/ffmpeg/gstffmpegcodecmap.h:
* ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_negotiate),
(gst_ffmpegdec_register):
* ext/ffmpeg/gstffmpegenc.c: (gst_ffmpegenc_getcaps),
(gst_ffmpegenc_register):
Add some more width/height/channels/rate limitations to caps
to cater for more automagic negotiation.  Addresses #532422.

ChangeLog
ext/ffmpeg/gstffmpegcodecmap.c
ext/ffmpeg/gstffmpegcodecmap.h
ext/ffmpeg/gstffmpegdec.c
ext/ffmpeg/gstffmpegenc.c

index 42a679e..21b30db 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2008-10-08  Mark Nauwelaerts  <mark.nauwelaerts@collabora.co.uk>
 
+       * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ff_vid_caps_new),
+       (gst_ff_aud_caps_new), (gst_ffmpeg_codecid_to_caps),
+       (gst_ffmpeg_codectype_to_caps):
+       * ext/ffmpeg/gstffmpegcodecmap.h:
+       * ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_negotiate),
+       (gst_ffmpegdec_register):
+       * ext/ffmpeg/gstffmpegenc.c: (gst_ffmpegenc_getcaps),
+       (gst_ffmpegenc_register):
+       Add some more width/height/channels/rate limitations to caps
+       to cater for more automagic negotiation.  Addresses #532422.
+
+2008-10-08  Mark Nauwelaerts  <mark.nauwelaerts@collabora.co.uk>
+
        * configure.ac:
        * ext/Makefile.am:
        * ext/libswscale/Makefile.am:
index 02001e0..2b51f1a 100644 (file)
@@ -87,14 +87,28 @@ gst_ff_vid_caps_new (AVCodecContext * context, enum CodecID codec_id,
   va_list var_args;
   gint i;
 
-  if (context != NULL) {
+  /* fixed, non probing context */
+  if (context != NULL && context->width != -1) {
     caps = gst_caps_new_simple (mimetype,
         "width", G_TYPE_INT, context->width,
         "height", G_TYPE_INT, context->height,
         "framerate", GST_TYPE_FRACTION,
         context->time_base.den, context->time_base.num, NULL);
-  } else {
+  } else if (context) {
+    /* so we are after restricted caps in this case */
     switch (codec_id) {
+      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;
+      }
       case CODEC_ID_H263:
       {
         /* 128x96, 176x144, 352x288, 704x576, and 1408x1152. slightly reordered
@@ -131,21 +145,37 @@ gst_ff_vid_caps_new (AVCodecContext * context, enum CodecID codec_id,
               "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
 
           gst_caps_append (caps, temp);
-       }
+        }
         break;
       }
-      default:
+      case CODEC_ID_DNXHD:
+      {
         caps = gst_caps_new_simple (mimetype,
-            "width", GST_TYPE_INT_RANGE, 16, 4096,
-            "height", GST_TYPE_INT_RANGE, 16, 4096,
+            "width", G_TYPE_INT, 1920,
+            "height", G_TYPE_INT, 1080,
             "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
+        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:
         break;
     }
   }
 
+  /* no fixed caps or special restrictions applied;
+   * default unfixed setting */
+  if (!caps)
+    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);
+
   for (i = 0; i < gst_caps_get_size (caps); i++) {
-    structure = gst_caps_get_structure (caps, i);
     va_start (var_args, fieldname);
+    structure = gst_caps_get_structure (caps, i);
     gst_structure_set_valist (structure, fieldname, var_args);
     va_end (var_args);
   }
@@ -162,36 +192,94 @@ gst_ff_aud_caps_new (AVCodecContext * context, enum CodecID codec_id,
 {
   GstCaps *caps = NULL;
   GstStructure *structure = NULL;
+  gint i;
   va_list var_args;
 
-  if (context != NULL) {
+  /* fixed, non-probing context */
+  if (context != NULL && context->channels != -1) {
     caps = gst_caps_new_simple (mimetype,
         "rate", G_TYPE_INT, context->sample_rate,
         "channels", G_TYPE_INT, context->channels, NULL);
   } else {
-    gint maxchannels;
-    /* Until decoders/encoders expose the maximum number of channels
-     * they support, we whitelist them here. */
-    switch (codec_id) {
-    case CODEC_ID_AC3:
-    case CODEC_ID_AAC:
-    case CODEC_ID_DTS:
-      maxchannels = 6;
-      break;
-    default:
-      maxchannels = 2;
-    }
+    gint maxchannels = 2;
+    const gint *rates = NULL;
+    gint n_rates = 0;
 
-    caps = gst_caps_new_simple (mimetype,
-        "rate", GST_TYPE_INT_RANGE, 8000, 96000,
-        "channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL);
+    if (context)
+      /* so we must be after restricted caps in this particular case */
+      switch (codec_id) {
+        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;
+        }
+        case CODEC_ID_AC3:
+        {
+          const static gint l_rates[] = { 48000, 44100, 32000 };
+          n_rates = G_N_ELEMENTS (l_rates);
+          rates = l_rates;
+          maxchannels = 6;
+          break;
+        }
+        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_ADPCM_G726:
+          maxchannels = 1;
+          break;
+        case CODEC_ID_AAC:
+        case CODEC_ID_DTS:
+          /* Until decoders/encoders expose the maximum number of channels
+           * they support, we whitelist them here. */
+          maxchannels = 6;
+          break;
+        default:
+          break;
+      }
 
+    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
+      gst_caps_set_simple (caps, "rate", GST_TYPE_INT_RANGE, 8000, 96000, NULL);
   }
 
-  structure = gst_caps_get_structure (caps, 0);
-
-  if (structure) {
+  for (i = 0; i < gst_caps_get_size (caps); i++) {
     va_start (var_args, fieldname);
+    structure = gst_caps_get_structure (caps, i);
     gst_structure_set_valist (structure, fieldname, var_args);
     va_end (var_args);
   }
@@ -428,7 +516,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id,
       break;
 
     case CODEC_ID_RAWVIDEO:
-      caps = gst_ffmpeg_codectype_to_caps (CODEC_TYPE_VIDEO, context, codec_id);
+      caps = gst_ffmpeg_codectype_to_caps (CODEC_TYPE_VIDEO, context, codec_id,
+          encode);
       break;
 
     case CODEC_ID_MSMPEG4V1:
@@ -1366,7 +1455,7 @@ gst_ffmpeg_smpfmt_to_caps (enum SampleFormat sample_fmt,
 
 GstCaps *
 gst_ffmpeg_codectype_to_caps (enum CodecType codec_type,
-    AVCodecContext * context, enum CodecID codec_id)
+    AVCodecContext * context, enum CodecID codec_id, gboolean encode)
 {
   GstCaps *caps;
 
@@ -1374,14 +1463,17 @@ gst_ffmpeg_codectype_to_caps (enum CodecType codec_type,
     case CODEC_TYPE_VIDEO:
       if (context) {
         caps = gst_ffmpeg_pixfmt_to_caps (context->pix_fmt,
-            context->width == -1 ? NULL : context, codec_id);
+            context, codec_id);
       } else {
         GstCaps *temp;
         enum PixelFormat i;
+        AVCodecContext ctx = { 0, };
 
         caps = gst_caps_new_empty ();
         for (i = 0; i < PIX_FMT_NB; i++) {
-          temp = gst_ffmpeg_pixfmt_to_caps (i, NULL, codec_id);
+          ctx.width = -1;
+          ctx.pix_fmt = i;
+          temp = gst_ffmpeg_pixfmt_to_caps (i, encode ? &ctx : NULL, codec_id);
           if (temp != NULL) {
             gst_caps_append (caps, temp);
           }
@@ -1396,10 +1488,12 @@ gst_ffmpeg_codectype_to_caps (enum CodecType codec_type,
       } else {
         GstCaps *temp;
         enum SampleFormat i;
+        AVCodecContext ctx = { 0, };
 
+        ctx.channels = -1;
         caps = gst_caps_new_empty ();
         for (i = 0; i <= SAMPLE_FMT_S16; i++) {
-          temp = gst_ffmpeg_smpfmt_to_caps (i, NULL, codec_id);
+          temp = gst_ffmpeg_smpfmt_to_caps (i, encode ? &ctx : NULL, codec_id);
           if (temp != NULL) {
             gst_caps_append (caps, temp);
           }
index 252b5de..605b279 100644 (file)
@@ -45,7 +45,8 @@ gst_ffmpeg_codecid_to_caps   (enum CodecID    codec_id,
 GstCaps *
 gst_ffmpeg_codectype_to_caps (enum CodecType  codec_type,
                               AVCodecContext *context, 
-                             enum CodecID codec_id);
+                              enum CodecID codec_id,
+                              gboolean encode);
 
 /*
  * caps_to_codecid () transforms a GstCaps that belongs to
index 8ef83da..bbb81a8 100644 (file)
@@ -1046,7 +1046,7 @@ gst_ffmpegdec_negotiate (GstFFMpegDec * ffmpegdec)
   }
 
   caps = gst_ffmpeg_codectype_to_caps (oclass->in_plugin->type,
-      ffmpegdec->context, oclass->in_plugin->id);
+      ffmpegdec->context, oclass->in_plugin->id, FALSE);
 
   if (caps == NULL)
     goto no_caps;
@@ -2497,8 +2497,8 @@ gst_ffmpegdec_register (GstPlugin * plugin)
     if (in_plugin->type == CODEC_TYPE_VIDEO) {
       srccaps = gst_caps_from_string ("video/x-raw-rgb; video/x-raw-yuv");
     } else {
-      srccaps =
-          gst_ffmpeg_codectype_to_caps (in_plugin->type, NULL, in_plugin->id);
+      srccaps = gst_ffmpeg_codectype_to_caps (in_plugin->type, NULL,
+          in_plugin->id, FALSE);
     }
     if (!srccaps) {
       GST_WARNING ("Couldn't get source caps for decoder %s",
index bc51699..087a68c 100644 (file)
@@ -286,6 +286,7 @@ gst_ffmpegenc_getcaps (GstPad * pad)
   AVCodecContext *ctx = NULL;
   enum PixelFormat pixfmt;
   GstCaps *caps = NULL;
+  gint i;
 
   GST_DEBUG_OBJECT (ffmpegenc, "getting caps");
 
@@ -317,9 +318,20 @@ gst_ffmpegenc_getcaps (GstPad * pad)
   _shut_up_I_am_probing = TRUE;
 #endif
   GST_DEBUG_OBJECT (ffmpegenc, "probing caps");
-  for (pixfmt = 0; pixfmt < PIX_FMT_NB; pixfmt++) {
+  i = pixfmt = 0;
+  /* check pixfmt until deemed finished */
+  for (pixfmt = 0;; pixfmt++) {
     GstCaps *tmpcaps;
 
+    /* override looping all pixfmt if codec declares pixfmts;
+     * these may not properly check and report supported pixfmt during _init */
+    if (oclass->in_plugin->pix_fmts) {
+      if ((pixfmt = oclass->in_plugin->pix_fmts[i++]) == PIX_FMT_NONE)
+        break;
+    }
+    if (pixfmt >= PIX_FMT_NB)
+      break;
+
     /* need to start with a fresh codec_context each time around, since
      * codec_close may have released stuff causing the next pass to segfault */
     ctx = avcodec_alloc_context ();
@@ -344,7 +356,7 @@ gst_ffmpegenc_getcaps (GstPad * pad)
       if (!caps)
         caps = gst_caps_new_empty ();
       tmpcaps = gst_ffmpeg_codectype_to_caps (oclass->in_plugin->type, ctx,
-          oclass->in_plugin->id);
+          oclass->in_plugin->id, TRUE);
       if (tmpcaps)
         gst_caps_append (caps, tmpcaps);
       else
@@ -1018,8 +1030,8 @@ gst_ffmpegenc_register (GstPlugin * plugin)
       sinkcaps = gst_caps_from_string
           ("video/x-raw-rgb; video/x-raw-yuv; video/x-raw-gray");
     } else {
-      sinkcaps =
-          gst_ffmpeg_codectype_to_caps (in_plugin->type, NULL, in_plugin->id);
+      sinkcaps = gst_ffmpeg_codectype_to_caps (in_plugin->type, NULL,
+          in_plugin->id, TRUE);
     }
     if (!sinkcaps) {
       GST_WARNING ("Couldn't get sink caps for encoder %s",