static GstFlowReturn gst_speex_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf) { GstSpeexEnc *enc; GstFlowReturn ret = GST_FLOW_OK; enc = GST_SPEEX_ENC (benc); if (!enc->header_sent) { /* Speex streams begin with two headers; the initial header (with most of the codec setup parameters) which is mandated by the Ogg bitstream spec. The second header holds any comment fields. We merely need to make the headers, then pass them to libspeex one at a time; libspeex handles the additional Ogg bitstream constraints */ GstBuffer *buf1, *buf2; GstCaps *caps; guchar *data; gint data_len; GList *headers; /* create header buffer */ data = (guint8 *) speex_header_to_packet (&enc->header, &data_len); buf1 = gst_buffer_new_wrapped (data, data_len); GST_BUFFER_OFFSET_END (buf1) = 0; GST_BUFFER_OFFSET (buf1) = 0; /* create comment buffer */ buf2 = gst_speex_enc_create_metadata_buffer (enc); /* mark and put on caps */ caps = gst_caps_new_simple ("audio/x-speex", "rate", G_TYPE_INT, enc->rate, "channels", G_TYPE_INT, enc->channels, NULL); caps = _gst_caps_set_buffer_array (caps, "streamheader", buf1, buf2, NULL); /* negotiate with these caps */ GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps); gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (enc), caps); gst_caps_unref (caps); /* push out buffers */ /* store buffers for later pre_push sending */ headers = NULL; GST_DEBUG_OBJECT (enc, "storing header buffers"); headers = g_list_prepend (headers, buf2); headers = g_list_prepend (headers, buf1); gst_audio_encoder_set_headers (benc, headers); enc->header_sent = TRUE; } GST_DEBUG_OBJECT (enc, "received buffer %p of %" G_GSIZE_FORMAT " bytes", buf, buf ? gst_buffer_get_size (buf) : 0); ret = gst_speex_enc_encode (enc, buf); return ret; }
static GstFlowReturn gst_vorbis_enc_handle_frame (GstAudioEncoder * enc, GstBuffer * buffer) { GstVorbisEnc *vorbisenc; GstFlowReturn ret = GST_FLOW_OK; GstMapInfo map; gfloat *ptr; gulong size; gulong i, j; float **vorbis_buffer; GstBuffer *buf1, *buf2, *buf3; vorbisenc = GST_VORBISENC (enc); if (G_UNLIKELY (!vorbisenc->setup)) { if (buffer) { GST_DEBUG_OBJECT (vorbisenc, "forcing setup"); /* should not fail, as setup before same way */ if (!gst_vorbis_enc_setup (vorbisenc)) return GST_FLOW_ERROR; } else { /* end draining */ GST_LOG_OBJECT (vorbisenc, "already drained"); return GST_FLOW_OK; } } if (!vorbisenc->header_sent) { /* Vorbis streams begin with three headers; the initial header (with most of the codec setup parameters) which is mandated by the Ogg bitstream spec. The second header holds any comment fields. The third header holds the bitstream codebook. We merely need to make the headers, then pass them to libvorbis one at a time; libvorbis handles the additional Ogg bitstream constraints */ ogg_packet header; ogg_packet header_comm; ogg_packet header_code; GstCaps *caps; GList *headers; GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets"); gst_vorbis_enc_set_metadata (vorbisenc); vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header, &header_comm, &header_code); vorbis_comment_clear (&vorbisenc->vc); /* create header buffers */ buf1 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header); buf2 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_comm); buf3 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_code); /* mark and put on caps */ caps = gst_caps_new_simple ("audio/x-vorbis", "rate", G_TYPE_INT, vorbisenc->frequency, "channels", G_TYPE_INT, vorbisenc->channels, NULL); caps = _gst_caps_set_buffer_array (caps, "streamheader", buf1, buf2, buf3, NULL); /* negotiate with these caps */ GST_DEBUG_OBJECT (vorbisenc, "here are the caps: %" GST_PTR_FORMAT, caps); gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (vorbisenc), caps); gst_caps_unref (caps); /* store buffers for later pre_push sending */ headers = NULL; GST_DEBUG_OBJECT (vorbisenc, "storing header buffers"); headers = g_list_prepend (headers, buf3); headers = g_list_prepend (headers, buf2); headers = g_list_prepend (headers, buf1); gst_audio_encoder_set_headers (enc, headers); vorbisenc->header_sent = TRUE; } if (!buffer) return gst_vorbis_enc_clear (vorbisenc); gst_buffer_map (buffer, &map, GST_MAP_WRITE); /* data to encode */ size = map.size / (vorbisenc->channels * sizeof (float)); ptr = (gfloat *) map.data; /* expose the buffer to submit data */ vorbis_buffer = vorbis_analysis_buffer (&vorbisenc->vd, size); /* deinterleave samples, write the buffer data */ if (vorbisenc->channels < 2 || vorbisenc->channels > 8) { for (i = 0; i < size; i++) { for (j = 0; j < vorbisenc->channels; j++) { vorbis_buffer[j][i] = *ptr++; } } } else { gint i, j; /* Reorder */ for (i = 0; i < size; i++) { for (j = 0; j < vorbisenc->channels; j++) { vorbis_buffer[gst_vorbis_reorder_map[vorbisenc->channels - 1][j]][i] = ptr[j]; } ptr += vorbisenc->channels; } } /* tell the library how much we actually submitted */ vorbis_analysis_wrote (&vorbisenc->vd, size); gst_buffer_unmap (buffer, &map); GST_LOG_OBJECT (vorbisenc, "wrote %lu samples to vorbis", size); ret = gst_vorbis_enc_output_buffers (vorbisenc); return ret; }
static GstFlowReturn gst_celt_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf) { GstCeltEnc *enc; GstFlowReturn ret = GST_FLOW_OK; enc = GST_CELT_ENC (benc); if (!enc->header_sent) { /* Celt streams begin with two headers; the initial header (with most of the codec setup parameters) which is mandated by the Ogg bitstream spec. The second header holds any comment fields. We merely need to make the headers, then pass them to libcelt one at a time; libcelt handles the additional Ogg bitstream constraints */ GstBuffer *buf1, *buf2; GstCaps *caps; /* libcelt has a bug which underestimates header size by 4... */ unsigned int header_size = enc->header.header_size + 4; unsigned char *data = g_malloc (header_size); GList *headers; /* create header buffer */ int error = celt_header_to_packet (&enc->header, data, header_size); if (error < 0) { g_free (data); goto no_header; } buf1 = gst_buffer_new_wrapped (data, header_size); GST_BUFFER_OFFSET_END (buf1) = 0; GST_BUFFER_OFFSET (buf1) = 0; /* create comment buffer */ buf2 = gst_celt_enc_create_metadata_buffer (enc); /* mark and put on caps */ caps = gst_caps_new_simple ("audio/x-celt", "rate", G_TYPE_INT, enc->rate, "channels", G_TYPE_INT, enc->channels, "frame-size", G_TYPE_INT, enc->frame_size, NULL); caps = _gst_caps_set_buffer_array (caps, "streamheader", buf1, buf2, NULL); /* negotiate with these caps */ GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps); GST_LOG_OBJECT (enc, "rate=%d channels=%d frame-size=%d", enc->rate, enc->channels, enc->frame_size); gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (enc), caps); gst_caps_unref (caps); /* push out buffers */ /* store buffers for later pre_push sending */ headers = NULL; GST_DEBUG_OBJECT (enc, "storing header buffers"); headers = g_list_prepend (headers, buf2); headers = g_list_prepend (headers, buf1); gst_audio_encoder_set_headers (benc, headers); enc->header_sent = TRUE; } GST_DEBUG_OBJECT (enc, "received buffer %p of %" G_GSIZE_FORMAT " bytes", buf, buf ? gst_buffer_get_size (buf) : 0); ret = gst_celt_enc_encode (enc, buf); done: return ret; /* ERRORS */ no_header: { GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL), ("Failed to encode header")); ret = GST_FLOW_ERROR; goto done; } }