static void gst_opus_enc_setup_base_class (GstOpusEnc * enc, GstAudioEncoder * benc) { gst_audio_encoder_set_latency (benc, gst_opus_enc_get_latency (enc), gst_opus_enc_get_latency (enc)); gst_audio_encoder_set_frame_samples_min (benc, enc->frame_samples); gst_audio_encoder_set_frame_samples_max (benc, enc->frame_samples); gst_audio_encoder_set_frame_max (benc, 1); }
static gboolean gst_speex_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info) { GstSpeexEnc *enc; enc = GST_SPEEX_ENC (benc); enc->channels = GST_AUDIO_INFO_CHANNELS (info); enc->rate = GST_AUDIO_INFO_RATE (info); /* handle reconfigure */ if (enc->state) { speex_encoder_destroy (enc->state); enc->state = NULL; } if (!gst_speex_enc_setup (enc)) return FALSE; /* feedback to base class */ gst_audio_encoder_set_latency (benc, gst_speex_enc_get_latency (enc), gst_speex_enc_get_latency (enc)); gst_audio_encoder_set_lookahead (benc, enc->lookahead); if (enc->nframes == 0) { /* as many frames as available input allows */ gst_audio_encoder_set_frame_samples_min (benc, enc->frame_size); gst_audio_encoder_set_frame_samples_max (benc, enc->frame_size); gst_audio_encoder_set_frame_max (benc, 0); } else { /* exactly as many frames as configured */ gst_audio_encoder_set_frame_samples_min (benc, enc->frame_size * enc->nframes); gst_audio_encoder_set_frame_samples_max (benc, enc->frame_size * enc->nframes); gst_audio_encoder_set_frame_max (benc, 1); } return TRUE; }
static gboolean gst_celt_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info) { GstCeltEnc *enc; GstCaps *otherpadcaps; enc = GST_CELT_ENC (benc); enc->channels = GST_AUDIO_INFO_CHANNELS (info); enc->rate = GST_AUDIO_INFO_RATE (info); /* handle reconfigure */ if (enc->state) { celt_encoder_destroy (enc->state); enc->state = NULL; } if (enc->mode) { celt_mode_destroy (enc->mode); enc->mode = NULL; } memset (&enc->header, 0, sizeof (enc->header)); otherpadcaps = gst_pad_get_allowed_caps (GST_AUDIO_ENCODER_SRC_PAD (enc)); if (otherpadcaps) { if (!gst_caps_is_empty (otherpadcaps)) { GstStructure *ps = gst_caps_get_structure (otherpadcaps, 0); gst_structure_get_int (ps, "frame-size", &enc->frame_size); } gst_caps_unref (otherpadcaps); } if (enc->requested_frame_size > 0) enc->frame_size = enc->requested_frame_size; GST_DEBUG_OBJECT (enc, "channels=%d rate=%d frame-size=%d", enc->channels, enc->rate, enc->frame_size); if (!gst_celt_enc_setup (enc)) return FALSE; /* feedback to base class */ gst_audio_encoder_set_latency (benc, gst_celt_enc_get_latency (enc), gst_celt_enc_get_latency (enc)); gst_audio_encoder_set_frame_samples_min (benc, enc->frame_size); gst_audio_encoder_set_frame_samples_max (benc, enc->frame_size); gst_audio_encoder_set_frame_max (benc, 1); return TRUE; }
static gboolean gst_gsmenc_set_format (GstAudioEncoder * benc, GstAudioInfo * info) { GstCaps *srccaps; srccaps = gst_static_pad_template_get_caps (&gsmenc_src_template); gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (benc), srccaps); /* report needs to base class */ gst_audio_encoder_set_frame_samples_min (benc, 160); gst_audio_encoder_set_frame_samples_max (benc, 160); gst_audio_encoder_set_frame_max (benc, 1); return TRUE; }
static gboolean gst_siren_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info) { gboolean res; GstCaps *outcaps; outcaps = gst_static_pad_template_get_caps (&srctemplate); res = gst_audio_encoder_set_output_format (benc, outcaps); gst_caps_unref (outcaps); /* report needs to base class */ gst_audio_encoder_set_frame_samples_min (benc, 320); gst_audio_encoder_set_frame_samples_max (benc, 320); /* no remainder or flushing please */ gst_audio_encoder_set_hard_min (benc, TRUE); gst_audio_encoder_set_drainable (benc, FALSE); return res; }
static gboolean gst_siren_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info) { GstSirenEnc *enc; gboolean res; GstCaps *outcaps; enc = GST_SIREN_ENC (benc); outcaps = gst_static_pad_template_get_caps (&srctemplate); res = gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc), outcaps); gst_caps_unref (outcaps); /* report needs to base class */ gst_audio_encoder_set_frame_samples_min (benc, 320); gst_audio_encoder_set_frame_samples_max (benc, 320); /* no remainder or flushing please */ gst_audio_encoder_set_hard_min (benc, TRUE); gst_audio_encoder_set_drainable (benc, FALSE); return res; }
static gboolean gst_amrnbenc_set_format (GstAudioEncoder * enc, GstAudioInfo * info) { GstAmrnbEnc *amrnbenc; GstCaps *copy; amrnbenc = GST_AMRNBENC (enc); /* parameters already parsed for us */ amrnbenc->rate = GST_AUDIO_INFO_RATE (info); amrnbenc->channels = GST_AUDIO_INFO_CHANNELS (info); /* we do not really accept other input, but anyway ... */ /* this is not wrong but will sound bad */ if (amrnbenc->channels != 1) { g_warning ("amrnbdec is only optimized for mono channels"); } if (amrnbenc->rate != 8000) { g_warning ("amrnbdec is only optimized for 8000 Hz samplerate"); } /* create reverse caps */ copy = gst_caps_new_simple ("audio/AMR", "channels", G_TYPE_INT, amrnbenc->channels, "rate", G_TYPE_INT, amrnbenc->rate, NULL); gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (amrnbenc), copy); gst_caps_unref (copy); /* report needs to base class: hand one frame at a time */ gst_audio_encoder_set_frame_samples_min (enc, 160); gst_audio_encoder_set_frame_samples_max (enc, 160); gst_audio_encoder_set_frame_max (enc, 1); return TRUE; }
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; }
static gboolean gst_two_lame_set_format (GstAudioEncoder * enc, GstAudioInfo * info) { GstTwoLame *twolame; gint out_samplerate; gint version; GstCaps *othercaps; twolame = GST_TWO_LAME (enc); /* parameters already parsed for us */ twolame->samplerate = GST_AUDIO_INFO_RATE (info); twolame->num_channels = GST_AUDIO_INFO_CHANNELS (info); twolame->float_input = !GST_AUDIO_INFO_IS_INTEGER (info); /* but we might be asked to reconfigure, so reset */ gst_two_lame_release_memory (twolame); GST_DEBUG_OBJECT (twolame, "setting up twolame"); if (!gst_two_lame_setup (twolame)) goto setup_failed; out_samplerate = twolame_get_out_samplerate (twolame->glopts); if (out_samplerate == 0) goto zero_output_rate; if (out_samplerate != twolame->samplerate) { GST_WARNING_OBJECT (twolame, "output samplerate %d is different from incoming samplerate %d", out_samplerate, twolame->samplerate); } version = twolame_get_version (twolame->glopts); if (version == TWOLAME_MPEG2) version = 2; else version = 1; othercaps = gst_caps_new_simple ("audio/mpeg", "mpegversion", G_TYPE_INT, 1, "mpegaudioversion", G_TYPE_INT, version, "layer", G_TYPE_INT, 2, "channels", G_TYPE_INT, twolame->mode == TWOLAME_MONO ? 1 : twolame->num_channels, "rate", G_TYPE_INT, out_samplerate, NULL); /* and use these caps */ gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (twolame), othercaps); gst_caps_unref (othercaps); /* report needs to base class: * hand one frame at a time, if we are pretty sure what a frame is */ if (out_samplerate == twolame->samplerate) { gst_audio_encoder_set_frame_samples_min (enc, 1152); gst_audio_encoder_set_frame_samples_max (enc, 1152); gst_audio_encoder_set_frame_max (enc, 1); } return TRUE; zero_output_rate: { GST_ELEMENT_ERROR (twolame, LIBRARY, SETTINGS, (NULL), ("TwoLAME decided on a zero sample rate")); return FALSE; } setup_failed: { GST_ELEMENT_ERROR (twolame, LIBRARY, SETTINGS, (_("Failed to configure TwoLAME encoder. Check your encoding parameters.")), (NULL)); return FALSE; } }
static gboolean gst_fdkaacenc_set_format (GstAudioEncoder * enc, GstAudioInfo * info) { GstFdkAacEnc *self = GST_FDKAACENC (enc); gboolean ret = FALSE; GstCaps *allowed_caps; GstCaps *src_caps; AACENC_ERROR err; gint transmux = 0, aot = AOT_AAC_LC; gint mpegversion = 4; CHANNEL_MODE channel_mode; AACENC_InfoStruct enc_info = { 0 }; gint bitrate; if (self->enc) { /* drain */ gst_fdkaacenc_handle_frame (enc, NULL); aacEncClose (&self->enc); } allowed_caps = gst_pad_get_allowed_caps (GST_AUDIO_ENCODER_SRC_PAD (self)); GST_DEBUG_OBJECT (self, "allowed caps: %" GST_PTR_FORMAT, allowed_caps); if (allowed_caps && gst_caps_get_size (allowed_caps) > 0) { GstStructure *s = gst_caps_get_structure (allowed_caps, 0); const gchar *str = NULL; if ((str = gst_structure_get_string (s, "stream-format"))) { if (strcmp (str, "adts") == 0) { GST_DEBUG_OBJECT (self, "use ADTS format for output"); transmux = 2; } else if (strcmp (str, "adif") == 0) { GST_DEBUG_OBJECT (self, "use ADIF format for output"); transmux = 1; } else if (strcmp (str, "raw") == 0) { GST_DEBUG_OBJECT (self, "use RAW format for output"); transmux = 0; } } gst_structure_get_int (s, "mpegversion", &mpegversion); } if (allowed_caps) gst_caps_unref (allowed_caps); err = aacEncOpen (&self->enc, 0, GST_AUDIO_INFO_CHANNELS (info)); if (err != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to open encoder: %d\n", err); return FALSE; } aot = AOT_AAC_LC; if ((err = aacEncoder_SetParam (self->enc, AACENC_AOT, aot)) != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to set AOT %d: %d\n", aot, err); return FALSE; } if ((err = aacEncoder_SetParam (self->enc, AACENC_SAMPLERATE, GST_AUDIO_INFO_RATE (info))) != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to set sample rate %d: %d\n", GST_AUDIO_INFO_RATE (info), err); return FALSE; } if (GST_AUDIO_INFO_CHANNELS (info) == 1) { channel_mode = MODE_1; self->need_reorder = FALSE; self->aac_positions = NULL; } else { guint64 in_channel_mask, out_channel_mask; gint i; for (i = 0; i < G_N_ELEMENTS (channel_layouts); i++) { if (channel_layouts[i].channels != GST_AUDIO_INFO_CHANNELS (info)) continue; gst_audio_channel_positions_to_mask (&GST_AUDIO_INFO_POSITION (info, 0), GST_AUDIO_INFO_CHANNELS (info), FALSE, &in_channel_mask); gst_audio_channel_positions_to_mask (channel_layouts[i].positions, channel_layouts[i].channels, FALSE, &out_channel_mask); if (in_channel_mask == out_channel_mask) { channel_mode = channel_layouts[i].mode; self->need_reorder = memcmp (channel_layouts[i].positions, &GST_AUDIO_INFO_POSITION (info, 0), GST_AUDIO_INFO_CHANNELS (info) * sizeof (GstAudioChannelPosition)) != 0; self->aac_positions = channel_layouts[i].positions; break; } } if (i == G_N_ELEMENTS (channel_layouts)) { GST_ERROR_OBJECT (self, "Couldn't find a valid channel layout"); return FALSE; } } if ((err = aacEncoder_SetParam (self->enc, AACENC_CHANNELMODE, channel_mode)) != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to set channel mode %d: %d", channel_mode, err); return FALSE; } /* MPEG channel order */ if ((err = aacEncoder_SetParam (self->enc, AACENC_CHANNELORDER, 0)) != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to set channel order %d: %d", channel_mode, err); return FALSE; } bitrate = self->bitrate; /* See * http://wiki.hydrogenaud.io/index.php?title=Fraunhofer_FDK_AAC#Recommended_Sampling_Rate_and_Bitrate_Combinations */ if (bitrate == 0) { if (GST_AUDIO_INFO_CHANNELS (info) == 1) { if (GST_AUDIO_INFO_RATE (info) < 16000) { bitrate = 8000; } else if (GST_AUDIO_INFO_RATE (info) == 16000) { bitrate = 16000; } else if (GST_AUDIO_INFO_RATE (info) < 32000) { bitrate = 24000; } else if (GST_AUDIO_INFO_RATE (info) == 32000) { bitrate = 32000; } else if (GST_AUDIO_INFO_RATE (info) <= 44100) { bitrate = 56000; } else { bitrate = 160000; } } else if (GST_AUDIO_INFO_CHANNELS (info) == 2) { if (GST_AUDIO_INFO_RATE (info) < 16000) { bitrate = 16000; } else if (GST_AUDIO_INFO_RATE (info) == 16000) { bitrate = 24000; } else if (GST_AUDIO_INFO_RATE (info) < 22050) { bitrate = 32000; } else if (GST_AUDIO_INFO_RATE (info) < 32000) { bitrate = 40000; } else if (GST_AUDIO_INFO_RATE (info) == 32000) { bitrate = 96000; } else if (GST_AUDIO_INFO_RATE (info) <= 44100) { bitrate = 112000; } else { bitrate = 320000; } } else { /* 5, 5.1 */ if (GST_AUDIO_INFO_RATE (info) < 32000) { bitrate = 160000; } else if (GST_AUDIO_INFO_RATE (info) <= 44100) { bitrate = 240000; } else { bitrate = 320000; } } } if ((err = aacEncoder_SetParam (self->enc, AACENC_TRANSMUX, transmux)) != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to set transmux %d: %d", transmux, err); return FALSE; } if ((err = aacEncoder_SetParam (self->enc, AACENC_BITRATE, bitrate)) != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to set bitrate %d: %d", bitrate, err); return FALSE; } if ((err = aacEncEncode (self->enc, NULL, NULL, NULL, NULL)) != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to initialize encoder: %d", err); return FALSE; } if ((err = aacEncInfo (self->enc, &enc_info)) != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to get encoder info: %d", err); return FALSE; } gst_audio_encoder_set_frame_max (enc, 1); gst_audio_encoder_set_frame_samples_min (enc, enc_info.frameLength); gst_audio_encoder_set_frame_samples_max (enc, enc_info.frameLength); gst_audio_encoder_set_hard_min (enc, FALSE); self->outbuf_size = enc_info.maxOutBufBytes; self->samples_per_frame = enc_info.frameLength; src_caps = gst_caps_new_simple ("audio/mpeg", "mpegversion", G_TYPE_INT, mpegversion, "channels", G_TYPE_INT, GST_AUDIO_INFO_CHANNELS (info), "framed", G_TYPE_BOOLEAN, TRUE, "rate", G_TYPE_INT, GST_AUDIO_INFO_RATE (info), NULL); /* raw */ if (transmux == 0) { GstBuffer *codec_data = gst_buffer_new_wrapped (g_memdup (enc_info.confBuf, enc_info.confSize), enc_info.confSize); gst_caps_set_simple (src_caps, "codec_data", GST_TYPE_BUFFER, codec_data, "stream-format", G_TYPE_STRING, "raw", NULL); gst_buffer_unref (codec_data); } else if (transmux == 1) { gst_caps_set_simple (src_caps, "stream-format", G_TYPE_STRING, "adif", NULL); } else if (transmux == 2) { gst_caps_set_simple (src_caps, "stream-format", G_TYPE_STRING, "adts", NULL); } else { g_assert_not_reached (); } gst_codec_utils_aac_caps_set_level_and_profile (src_caps, enc_info.confBuf, enc_info.confSize); ret = gst_audio_encoder_set_output_format (enc, src_caps); gst_caps_unref (src_caps); return ret; }
static gboolean gst_sbc_enc_set_format (GstAudioEncoder * audio_enc, GstAudioInfo * info) { const gchar *allocation_method, *channel_mode; GstSbcEnc *enc = GST_SBC_ENC (audio_enc); GstStructure *s; GstCaps *caps, *filter_caps; GstCaps *output_caps = NULL; guint sampleframes_per_frame; enc->rate = GST_AUDIO_INFO_RATE (info); enc->channels = GST_AUDIO_INFO_CHANNELS (info); /* negotiate output format based on downstream caps restrictions */ caps = gst_pad_get_allowed_caps (GST_AUDIO_ENCODER_SRC_PAD (enc)); if (caps == GST_CAPS_NONE || gst_caps_is_empty (caps)) goto failure; if (caps == NULL) caps = gst_static_pad_template_get_caps (&sbc_enc_src_factory); /* fixate output caps */ filter_caps = gst_caps_new_simple ("audio/x-sbc", "rate", G_TYPE_INT, enc->rate, "channels", G_TYPE_INT, enc->channels, NULL); output_caps = gst_caps_intersect (caps, filter_caps); gst_caps_unref (filter_caps); if (output_caps == NULL || gst_caps_is_empty (output_caps)) { GST_WARNING_OBJECT (enc, "Couldn't negotiate output caps with input rate " "%d and input channels %d and allowed output caps %" GST_PTR_FORMAT, enc->rate, enc->channels, caps); goto failure; } gst_caps_unref (caps); caps = NULL; GST_DEBUG_OBJECT (enc, "fixating caps %" GST_PTR_FORMAT, output_caps); output_caps = gst_caps_truncate (output_caps); s = gst_caps_get_structure (output_caps, 0); if (enc->channels == 1) gst_structure_fixate_field_string (s, "channel-mode", "mono"); else gst_structure_fixate_field_string (s, "channel-mode", "joint"); gst_structure_fixate_field_nearest_int (s, "bitpool", 64); gst_structure_fixate_field_nearest_int (s, "blocks", 16); gst_structure_fixate_field_nearest_int (s, "subbands", 8); gst_structure_fixate_field_string (s, "allocation-method", "loudness"); s = NULL; /* in case there's anything else left to fixate */ output_caps = gst_caps_fixate (output_caps); gst_caps_set_simple (output_caps, "parsed", G_TYPE_BOOLEAN, TRUE, NULL); GST_INFO_OBJECT (enc, "output caps %" GST_PTR_FORMAT, output_caps); /* let's see what we fixated to */ s = gst_caps_get_structure (output_caps, 0); gst_structure_get_int (s, "blocks", &enc->blocks); gst_structure_get_int (s, "subbands", &enc->subbands); gst_structure_get_int (s, "bitpool", &enc->bitpool); allocation_method = gst_structure_get_string (s, "allocation-method"); channel_mode = gst_structure_get_string (s, "channel-mode"); /* We want channel-mode and channels coherent */ if (enc->channels == 1) { if (g_strcmp0 (channel_mode, "mono") != 0) { GST_ERROR_OBJECT (enc, "Can't have channel-mode '%s' for 1 channel", channel_mode); goto failure; } } else { if (g_strcmp0 (channel_mode, "joint") != 0 && g_strcmp0 (channel_mode, "stereo") != 0 && g_strcmp0 (channel_mode, "dual") != 0) { GST_ERROR_OBJECT (enc, "Can't have channel-mode '%s' for 2 channels", channel_mode); goto failure; } } /* we want to be handed all available samples in handle_frame, but always * enough to encode a frame */ sampleframes_per_frame = enc->blocks * enc->subbands; gst_audio_encoder_set_frame_samples_min (audio_enc, sampleframes_per_frame); gst_audio_encoder_set_frame_samples_max (audio_enc, sampleframes_per_frame); gst_audio_encoder_set_frame_max (audio_enc, 0); /* FIXME: what to do with left-over samples at the end? can we encode them? */ gst_audio_encoder_set_hard_min (audio_enc, TRUE); /* and configure encoder based on the output caps we negotiated */ if (enc->rate == 16000) enc->sbc.frequency = SBC_FREQ_16000; else if (enc->rate == 32000) enc->sbc.frequency = SBC_FREQ_32000; else if (enc->rate == 44100) enc->sbc.frequency = SBC_FREQ_44100; else if (enc->rate == 48000) enc->sbc.frequency = SBC_FREQ_48000; else goto failure; if (enc->blocks == 4) enc->sbc.blocks = SBC_BLK_4; else if (enc->blocks == 8) enc->sbc.blocks = SBC_BLK_8; else if (enc->blocks == 12) enc->sbc.blocks = SBC_BLK_12; else if (enc->blocks == 16) enc->sbc.blocks = SBC_BLK_16; else goto failure; enc->sbc.subbands = (enc->subbands == 4) ? SBC_SB_4 : SBC_SB_8; enc->sbc.bitpool = enc->bitpool; if (channel_mode == NULL || allocation_method == NULL) goto failure; if (strcmp (channel_mode, "joint") == 0) enc->sbc.mode = SBC_MODE_JOINT_STEREO; else if (strcmp (channel_mode, "stereo") == 0) enc->sbc.mode = SBC_MODE_STEREO; else if (strcmp (channel_mode, "dual") == 0) enc->sbc.mode = SBC_MODE_DUAL_CHANNEL; else if (strcmp (channel_mode, "mono") == 0) enc->sbc.mode = SBC_MODE_MONO; else if (strcmp (channel_mode, "auto") == 0) enc->sbc.mode = SBC_MODE_JOINT_STEREO; else goto failure; if (strcmp (allocation_method, "loudness") == 0) enc->sbc.allocation = SBC_AM_LOUDNESS; else if (strcmp (allocation_method, "snr") == 0) enc->sbc.allocation = SBC_AM_SNR; else goto failure; if (!gst_audio_encoder_set_output_format (audio_enc, output_caps)) goto failure; return gst_audio_encoder_negotiate (audio_enc); failure: if (output_caps) gst_caps_unref (output_caps); if (caps) gst_caps_unref (caps); return FALSE; }
static gboolean gst_omx_audio_enc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info) { GstOMXAudioEnc *self; GstOMXAudioEncClass *klass; gboolean needs_disable = FALSE; OMX_PARAM_PORTDEFINITIONTYPE port_def; OMX_AUDIO_PARAM_PCMMODETYPE pcm_param; gint i; OMX_ERRORTYPE err; self = GST_OMX_AUDIO_ENC (encoder); klass = GST_OMX_AUDIO_ENC_GET_CLASS (encoder); GST_DEBUG_OBJECT (self, "Setting new caps"); /* Set audio encoder base class properties */ gst_audio_encoder_set_frame_samples_min (encoder, gst_util_uint64_scale_ceil (OMX_MIN_PCMPAYLOAD_MSEC, GST_MSECOND * info->rate, GST_SECOND)); gst_audio_encoder_set_frame_samples_max (encoder, 0); gst_omx_port_get_port_definition (self->enc_in_port, &port_def); needs_disable = gst_omx_component_get_state (self->enc, GST_CLOCK_TIME_NONE) != OMX_StateLoaded; /* If the component is not in Loaded state and a real format change happens * we have to disable the port and re-allocate all buffers. If no real * format change happened we can just exit here. */ if (needs_disable) { GST_DEBUG_OBJECT (self, "Need to disable and drain encoder"); gst_omx_audio_enc_drain (self); gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE); /* Wait until the srcpad loop is finished, * unlock GST_AUDIO_ENCODER_STREAM_LOCK to prevent deadlocks * caused by using this lock from inside the loop function */ GST_AUDIO_ENCODER_STREAM_UNLOCK (self); gst_pad_stop_task (GST_AUDIO_ENCODER_SRC_PAD (encoder)); GST_AUDIO_ENCODER_STREAM_LOCK (self); if (gst_omx_port_set_enabled (self->enc_in_port, FALSE) != OMX_ErrorNone) return FALSE; if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone) return FALSE; if (gst_omx_port_wait_buffers_released (self->enc_in_port, 5 * GST_SECOND) != OMX_ErrorNone) return FALSE; if (gst_omx_port_wait_buffers_released (self->enc_out_port, 1 * GST_SECOND) != OMX_ErrorNone) return FALSE; if (gst_omx_port_deallocate_buffers (self->enc_in_port) != OMX_ErrorNone) return FALSE; if (gst_omx_port_deallocate_buffers (self->enc_out_port) != OMX_ErrorNone) return FALSE; if (gst_omx_port_wait_enabled (self->enc_in_port, 1 * GST_SECOND) != OMX_ErrorNone) return FALSE; if (gst_omx_port_wait_enabled (self->enc_out_port, 1 * GST_SECOND) != OMX_ErrorNone) return FALSE; GST_DEBUG_OBJECT (self, "Encoder drained and disabled"); } port_def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; GST_DEBUG_OBJECT (self, "Setting inport port definition"); if (gst_omx_port_update_port_definition (self->enc_in_port, &port_def) != OMX_ErrorNone) return FALSE; GST_OMX_INIT_STRUCT (&pcm_param); pcm_param.nPortIndex = self->enc_in_port->index; pcm_param.nChannels = info->channels; pcm_param.eNumData = ((info->finfo->flags & GST_AUDIO_FORMAT_FLAG_SIGNED) ? OMX_NumericalDataSigned : OMX_NumericalDataUnsigned); pcm_param.eEndian = ((info->finfo->endianness == G_LITTLE_ENDIAN) ? OMX_EndianLittle : OMX_EndianBig); pcm_param.bInterleaved = OMX_TRUE; pcm_param.nBitPerSample = info->finfo->width; pcm_param.nSamplingRate = info->rate; pcm_param.ePCMMode = OMX_AUDIO_PCMModeLinear; for (i = 0; i < pcm_param.nChannels; i++) { OMX_AUDIO_CHANNELTYPE pos; switch (info->position[i]) { case GST_AUDIO_CHANNEL_POSITION_MONO: case GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER: pos = OMX_AUDIO_ChannelCF; break; case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT: pos = OMX_AUDIO_ChannelLF; break; case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT: pos = OMX_AUDIO_ChannelRF; break; case GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT: pos = OMX_AUDIO_ChannelLS; break; case GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT: pos = OMX_AUDIO_ChannelRS; break; case GST_AUDIO_CHANNEL_POSITION_LFE1: pos = OMX_AUDIO_ChannelLFE; break; case GST_AUDIO_CHANNEL_POSITION_REAR_CENTER: pos = OMX_AUDIO_ChannelCS; break; case GST_AUDIO_CHANNEL_POSITION_REAR_LEFT: pos = OMX_AUDIO_ChannelLR; break; case GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT: pos = OMX_AUDIO_ChannelRR; break; default: pos = OMX_AUDIO_ChannelNone; break; } pcm_param.eChannelMapping[i] = pos; } GST_DEBUG_OBJECT (self, "Setting PCM parameters"); err = gst_omx_component_set_parameter (self->enc, OMX_IndexParamAudioPcm, &pcm_param); if (err != OMX_ErrorNone) { GST_ERROR_OBJECT (self, "Failed to set PCM parameters: %s (0x%08x)", gst_omx_error_to_string (err), err); return FALSE; } if (klass->set_format) { if (!klass->set_format (self, self->enc_in_port, info)) { GST_ERROR_OBJECT (self, "Subclass failed to set the new format"); return FALSE; } } GST_DEBUG_OBJECT (self, "Updating outport port definition"); if (gst_omx_port_update_port_definition (self->enc_out_port, NULL) != OMX_ErrorNone) return FALSE; GST_DEBUG_OBJECT (self, "Enabling component"); if (needs_disable) { if (gst_omx_port_set_enabled (self->enc_in_port, TRUE) != OMX_ErrorNone) return FALSE; if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone) return FALSE; if (gst_omx_port_wait_enabled (self->enc_in_port, 5 * GST_SECOND) != OMX_ErrorNone) return FALSE; if (gst_omx_port_mark_reconfigured (self->enc_in_port) != OMX_ErrorNone) return FALSE; } else { /* Disable output port */ if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone) return FALSE; if (gst_omx_port_wait_enabled (self->enc_out_port, 1 * GST_SECOND) != OMX_ErrorNone) return FALSE; if (gst_omx_component_set_state (self->enc, OMX_StateIdle) != OMX_ErrorNone) return FALSE; /* Need to allocate buffers to reach Idle state */ if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone) return FALSE; if (gst_omx_component_get_state (self->enc, GST_CLOCK_TIME_NONE) != OMX_StateIdle) return FALSE; if (gst_omx_component_set_state (self->enc, OMX_StateExecuting) != OMX_ErrorNone) return FALSE; if (gst_omx_component_get_state (self->enc, GST_CLOCK_TIME_NONE) != OMX_StateExecuting) return FALSE; } /* Unset flushing to allow ports to accept data again */ gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, FALSE); gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, FALSE); if (gst_omx_component_get_last_error (self->enc) != OMX_ErrorNone) { GST_ERROR_OBJECT (self, "Component in error state: %s (0x%08x)", gst_omx_component_get_last_error_string (self->enc), gst_omx_component_get_last_error (self->enc)); return FALSE; } /* Start the srcpad loop again */ GST_DEBUG_OBJECT (self, "Starting task again"); self->downstream_flow_ret = GST_FLOW_OK; gst_pad_start_task (GST_AUDIO_ENCODER_SRC_PAD (self), (GstTaskFunction) gst_omx_audio_enc_loop, encoder, NULL); return TRUE; }
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; }