示例#1
0
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;
}
示例#3
0
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;
  }
}