Esempio n. 1
0
static gboolean
gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegdec, gboolean force)
{
  GstFFMpegAudDecClass *oclass;
  gint depth;
  GstAudioFormat format;
  GstAudioChannelPosition pos[64] = { 0, };

  oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));

  depth = av_smp_format_depth (ffmpegdec->context->sample_fmt) * 8;
  format = gst_ffmpeg_smpfmt_to_audioformat (ffmpegdec->context->sample_fmt);
  if (format == GST_AUDIO_FORMAT_UNKNOWN)
    goto no_caps;

  if (!force && ffmpegdec->info.rate ==
      ffmpegdec->context->sample_rate &&
      ffmpegdec->info.channels == ffmpegdec->context->channels &&
      ffmpegdec->info.finfo->depth == depth)
    return TRUE;

  GST_DEBUG_OBJECT (ffmpegdec,
      "Renegotiating audio from %dHz@%dchannels (%d) to %dHz@%dchannels (%d)",
      ffmpegdec->info.rate, ffmpegdec->info.channels,
      ffmpegdec->info.finfo->depth,
      ffmpegdec->context->sample_rate, ffmpegdec->context->channels, depth);

  gst_ffmpeg_channel_layout_to_gst (ffmpegdec->context->channel_layout,
      ffmpegdec->context->channels, pos);
  memcpy (ffmpegdec->ffmpeg_layout, pos,
      sizeof (GstAudioChannelPosition) * ffmpegdec->context->channels);

  /* Get GStreamer channel layout */
  gst_audio_channel_positions_to_valid_order (pos,
      ffmpegdec->context->channels);
  ffmpegdec->needs_reorder =
      memcmp (pos, ffmpegdec->ffmpeg_layout,
      sizeof (pos[0]) * ffmpegdec->context->channels) != 0;
  gst_audio_info_set_format (&ffmpegdec->info, format,
      ffmpegdec->context->sample_rate, ffmpegdec->context->channels, pos);

  if (!gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (ffmpegdec),
          &ffmpegdec->info))
    goto caps_failed;

  return TRUE;

  /* ERRORS */
no_caps:
  {
#ifdef HAVE_LIBAV_UNINSTALLED
    /* using internal ffmpeg snapshot */
    GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION,
        ("Could not find GStreamer caps mapping for libav codec '%s'.",
            oclass->in_plugin->name), (NULL));
#else
    /* using external ffmpeg */
    GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION,
        ("Could not find GStreamer caps mapping for libav codec '%s', and "
            "you are using an external libavcodec. This is most likely due to "
            "a packaging problem and/or libavcodec having been upgraded to a "
            "version that is not compatible with this version of "
            "gstreamer-libav. Make sure your gstreamer-libav and libavcodec "
            "packages come from the same source/repository.",
            oclass->in_plugin->name), (NULL));
#endif
    return FALSE;
  }
caps_failed:
  {
    GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION, (NULL),
        ("Could not set caps for libav decoder (%s), not fixed?",
            oclass->in_plugin->name));

    return FALSE;
  }
}
Esempio n. 2
0
static gboolean
gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
{
  GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
  GstCaps *other_caps;
  GstCaps *allowed_caps;
  GstCaps *icaps;
  gsize frame_size;
  GstFFMpegAudEncClass *oclass =
      (GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc);

  /* close old session */
  if (ffmpegaudenc->opened) {
    gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
    ffmpegaudenc->opened = FALSE;
  }

  /* if we set it in _getcaps we should set it also in _link */
  ffmpegaudenc->context->strict_std_compliance = -1;

  /* user defined properties */
  if (ffmpegaudenc->bitrate > 0) {
    GST_INFO_OBJECT (ffmpegaudenc, "Setting avcontext to bitrate %d",
        ffmpegaudenc->bitrate);
    ffmpegaudenc->context->bit_rate = ffmpegaudenc->bitrate;
    ffmpegaudenc->context->bit_rate_tolerance = ffmpegaudenc->bitrate;
  } else {
    GST_INFO_OBJECT (ffmpegaudenc, "Using avcontext default bitrate %d",
        ffmpegaudenc->context->bit_rate);
  }

  /* RTP payload used for GOB production (for Asterisk) */
  if (ffmpegaudenc->rtp_payload_size) {
    ffmpegaudenc->context->rtp_payload_size = ffmpegaudenc->rtp_payload_size;
  }

  /* some other defaults */
  ffmpegaudenc->context->rc_strategy = 2;
  ffmpegaudenc->context->b_frame_strategy = 0;
  ffmpegaudenc->context->coder_type = 0;
  ffmpegaudenc->context->context_model = 0;
  ffmpegaudenc->context->scenechange_threshold = 0;
  ffmpegaudenc->context->inter_threshold = 0;

  /* fetch pix_fmt and so on */
  gst_ffmpeg_audioinfo_to_context (info, ffmpegaudenc->context);
  if (!ffmpegaudenc->context->time_base.den) {
    ffmpegaudenc->context->time_base.den = GST_AUDIO_INFO_RATE (info);
    ffmpegaudenc->context->time_base.num = 1;
    ffmpegaudenc->context->ticks_per_frame = 1;
  }

  if (ffmpegaudenc->context->channel_layout) {
    gst_ffmpeg_channel_layout_to_gst (ffmpegaudenc->context->channel_layout,
        ffmpegaudenc->context->channels, ffmpegaudenc->ffmpeg_layout);
    ffmpegaudenc->needs_reorder =
        (memcmp (ffmpegaudenc->ffmpeg_layout, info->position,
            sizeof (GstAudioChannelPosition) *
            ffmpegaudenc->context->channels) != 0);
  }

  /* open codec */
  if (gst_ffmpeg_avcodec_open (ffmpegaudenc->context, oclass->in_plugin) < 0) {
    if (ffmpegaudenc->context->priv_data)
      gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
    GST_DEBUG_OBJECT (ffmpegaudenc, "avenc_%s: Failed to open FFMPEG codec",
        oclass->in_plugin->name);
    return FALSE;
  }

  /* some codecs support more than one format, first auto-choose one */
  GST_DEBUG_OBJECT (ffmpegaudenc, "picking an output format ...");
  allowed_caps = gst_pad_get_allowed_caps (GST_AUDIO_ENCODER_SRC_PAD (encoder));
  if (!allowed_caps) {
    GST_DEBUG_OBJECT (ffmpegaudenc, "... but no peer, using template caps");
    /* we need to copy because get_allowed_caps returns a ref, and
     * get_pad_template_caps doesn't */
    allowed_caps =
        gst_pad_get_pad_template_caps (GST_AUDIO_ENCODER_SRC_PAD (encoder));
  }
  GST_DEBUG_OBJECT (ffmpegaudenc, "chose caps %" GST_PTR_FORMAT, allowed_caps);
  gst_ffmpeg_caps_with_codecid (oclass->in_plugin->id,
      oclass->in_plugin->type, allowed_caps, ffmpegaudenc->context);

  /* try to set this caps on the other side */
  other_caps = gst_ffmpeg_codecid_to_caps (oclass->in_plugin->id,
      ffmpegaudenc->context, TRUE);

  if (!other_caps) {
    gst_caps_unref (allowed_caps);
    gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
    GST_DEBUG ("Unsupported codec - no caps found");
    return FALSE;
  }

  icaps = gst_caps_intersect (allowed_caps, other_caps);
  gst_caps_unref (allowed_caps);
  gst_caps_unref (other_caps);
  if (gst_caps_is_empty (icaps)) {
    gst_caps_unref (icaps);
    return FALSE;
  }
  icaps = gst_caps_truncate (icaps);

  if (!gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (ffmpegaudenc),
          icaps)) {
    gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
    gst_caps_unref (icaps);
    return FALSE;
  }
  gst_caps_unref (icaps);

  frame_size = ffmpegaudenc->context->frame_size;
  if (frame_size > 1) {
    gst_audio_encoder_set_frame_samples_min (GST_AUDIO_ENCODER (ffmpegaudenc),
        frame_size);
    gst_audio_encoder_set_frame_samples_max (GST_AUDIO_ENCODER (ffmpegaudenc),
        frame_size);
    gst_audio_encoder_set_frame_max (GST_AUDIO_ENCODER (ffmpegaudenc), 1);
  } else {
    gst_audio_encoder_set_frame_samples_min (GST_AUDIO_ENCODER (ffmpegaudenc),
        0);
    gst_audio_encoder_set_frame_samples_max (GST_AUDIO_ENCODER (ffmpegaudenc),
        0);
    gst_audio_encoder_set_frame_max (GST_AUDIO_ENCODER (ffmpegaudenc), 0);
  }

  /* success! */
  ffmpegaudenc->opened = TRUE;

  return TRUE;
}
Esempio n. 3
0
static gboolean
gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
{
    GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
    GstCaps *other_caps;
    GstCaps *allowed_caps;
    GstCaps *icaps;
    gsize frame_size;
    GstFFMpegAudEncClass *oclass =
        (GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc);

    /* close old session */
    if (ffmpegaudenc->opened) {
        gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
        ffmpegaudenc->opened = FALSE;
        if (avcodec_get_context_defaults3 (ffmpegaudenc->context,
                                           oclass->in_plugin) < 0) {
            GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
            return FALSE;
        }
    }

    /* if we set it in _getcaps we should set it also in _link */
    ffmpegaudenc->context->strict_std_compliance = ffmpegaudenc->compliance;

    /* user defined properties */
    if (ffmpegaudenc->bitrate > 0) {
        GST_INFO_OBJECT (ffmpegaudenc, "Setting avcontext to bitrate %d",
                         ffmpegaudenc->bitrate);
        ffmpegaudenc->context->bit_rate = ffmpegaudenc->bitrate;
        ffmpegaudenc->context->bit_rate_tolerance = ffmpegaudenc->bitrate;
    } else {
        GST_INFO_OBJECT (ffmpegaudenc,
                         "Using avcontext default bitrate %" G_GINT64_FORMAT,
                         (gint64) ffmpegaudenc->context->bit_rate);
    }

    /* RTP payload used for GOB production (for Asterisk) */
    if (ffmpegaudenc->rtp_payload_size) {
        ffmpegaudenc->context->rtp_payload_size = ffmpegaudenc->rtp_payload_size;
    }

    /* some other defaults */
    ffmpegaudenc->context->rc_strategy = 2;
    ffmpegaudenc->context->b_frame_strategy = 0;
    ffmpegaudenc->context->coder_type = 0;
    ffmpegaudenc->context->context_model = 0;
    ffmpegaudenc->context->scenechange_threshold = 0;

    /* fetch pix_fmt and so on */
    gst_ffmpeg_audioinfo_to_context (info, ffmpegaudenc->context);
    if (!ffmpegaudenc->context->time_base.den) {
        ffmpegaudenc->context->time_base.den = GST_AUDIO_INFO_RATE (info);
        ffmpegaudenc->context->time_base.num = 1;
        ffmpegaudenc->context->ticks_per_frame = 1;
    }

    if (ffmpegaudenc->context->channel_layout) {
        gst_ffmpeg_channel_layout_to_gst (ffmpegaudenc->context->channel_layout,
                                          ffmpegaudenc->context->channels, ffmpegaudenc->ffmpeg_layout);
        ffmpegaudenc->needs_reorder =
            (memcmp (ffmpegaudenc->ffmpeg_layout, info->position,
                     sizeof (GstAudioChannelPosition) *
                     ffmpegaudenc->context->channels) != 0);
    }

    /* some codecs support more than one format, first auto-choose one */
    GST_DEBUG_OBJECT (ffmpegaudenc, "picking an output format ...");
    allowed_caps = gst_pad_get_allowed_caps (GST_AUDIO_ENCODER_SRC_PAD (encoder));
    if (!allowed_caps) {
        GST_DEBUG_OBJECT (ffmpegaudenc, "... but no peer, using template caps");
        /* we need to copy because get_allowed_caps returns a ref, and
         * get_pad_template_caps doesn't */
        allowed_caps =
            gst_pad_get_pad_template_caps (GST_AUDIO_ENCODER_SRC_PAD (encoder));
    }
    GST_DEBUG_OBJECT (ffmpegaudenc, "chose caps %" GST_PTR_FORMAT, allowed_caps);
    gst_ffmpeg_caps_with_codecid (oclass->in_plugin->id,
                                  oclass->in_plugin->type, allowed_caps, ffmpegaudenc->context);

    /* open codec */
    if (gst_ffmpeg_avcodec_open (ffmpegaudenc->context, oclass->in_plugin) < 0) {
        gst_caps_unref (allowed_caps);
        gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
        GST_DEBUG_OBJECT (ffmpegaudenc, "avenc_%s: Failed to open FFMPEG codec",
                          oclass->in_plugin->name);
        if (avcodec_get_context_defaults3 (ffmpegaudenc->context,
                                           oclass->in_plugin) < 0)
            GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");

        if ((oclass->in_plugin->capabilities & CODEC_CAP_EXPERIMENTAL) &&
                ffmpegaudenc->compliance != GST_FFMPEG_EXPERIMENTAL) {
            GST_ELEMENT_ERROR (ffmpegaudenc, LIBRARY, SETTINGS,
                               ("Codec is experimental, but settings don't allow encoders to "
                                "produce output of experimental quality"),
                               ("This codec may not create output that is conformant to the specs "
                                "or of good quality. If you must use it anyway, set the "
                                "compliance property to experimental"));
        }
        return FALSE;
    }

    /* try to set this caps on the other side */
    other_caps = gst_ffmpeg_codecid_to_caps (oclass->in_plugin->id,
                 ffmpegaudenc->context, TRUE);

    if (!other_caps) {
        gst_caps_unref (allowed_caps);
        gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
        GST_DEBUG ("Unsupported codec - no caps found");
        if (avcodec_get_context_defaults3 (ffmpegaudenc->context,
                                           oclass->in_plugin) < 0)
            GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
        return FALSE;
    }

    icaps = gst_caps_intersect (allowed_caps, other_caps);
    gst_caps_unref (allowed_caps);
    gst_caps_unref (other_caps);
    if (gst_caps_is_empty (icaps)) {
        gst_caps_unref (icaps);
        return FALSE;
    }
    icaps = gst_caps_fixate (icaps);

    if (!gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (ffmpegaudenc),
            icaps)) {
        gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
        gst_caps_unref (icaps);
        if (avcodec_get_context_defaults3 (ffmpegaudenc->context,
                                           oclass->in_plugin) < 0)
            GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
        return FALSE;
    }
    gst_caps_unref (icaps);

    frame_size = ffmpegaudenc->context->frame_size;
    if (frame_size > 1) {
        gst_audio_encoder_set_frame_samples_min (GST_AUDIO_ENCODER (ffmpegaudenc),
                frame_size);
        gst_audio_encoder_set_frame_samples_max (GST_AUDIO_ENCODER (ffmpegaudenc),
                frame_size);
        gst_audio_encoder_set_frame_max (GST_AUDIO_ENCODER (ffmpegaudenc), 1);
    } else {
        gst_audio_encoder_set_frame_samples_min (GST_AUDIO_ENCODER (ffmpegaudenc),
                0);
        gst_audio_encoder_set_frame_samples_max (GST_AUDIO_ENCODER (ffmpegaudenc),
                0);
        gst_audio_encoder_set_frame_max (GST_AUDIO_ENCODER (ffmpegaudenc), 0);
    }

    /* Store some tags */
    {
        GstTagList *tags = gst_tag_list_new_empty ();
        const gchar *codec;

        gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_NOMINAL_BITRATE,
                          (guint) ffmpegaudenc->context->bit_rate, NULL);

        if ((codec =
                    gst_ffmpeg_get_codecid_longname (ffmpegaudenc->context->codec_id)))
            gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_AUDIO_CODEC, codec,
                              NULL);

        gst_audio_encoder_merge_tags (encoder, tags, GST_TAG_MERGE_REPLACE);
        gst_tag_list_unref (tags);
    }

    /* success! */
    ffmpegaudenc->opened = TRUE;

    return TRUE;
}