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_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; }