예제 #1
0
/* FIXME 0.11: remove tag handling and let container take care of that? */
static GstFlowReturn
vorbis_handle_comment_packet (GstVorbisDec * vd, ogg_packet * packet)
{
  guint bitrate = 0;
  gchar *encoder = NULL;
  GstTagList *list;
  guint8 *data;
  gsize size;

  GST_DEBUG_OBJECT (vd, "parsing comment packet");

  data = gst_ogg_packet_data (packet);
  size = gst_ogg_packet_size (packet);

  list =
      gst_tag_list_from_vorbiscomment (data, size, (guint8 *) "\003vorbis", 7,
      &encoder);

  if (!list) {
    GST_ERROR_OBJECT (vd, "couldn't decode comments");
    list = gst_tag_list_new_empty ();
  }

  if (encoder) {
    if (encoder[0])
      gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
          GST_TAG_ENCODER, encoder, NULL);
    g_free (encoder);
  }
  gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
      GST_TAG_ENCODER_VERSION, vd->vi.version,
      GST_TAG_AUDIO_CODEC, "Vorbis", NULL);
  if (vd->vi.bitrate_nominal > 0 && vd->vi.bitrate_nominal <= 0x7FFFFFFF) {
    gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
        GST_TAG_NOMINAL_BITRATE, (guint) vd->vi.bitrate_nominal, NULL);
    bitrate = vd->vi.bitrate_nominal;
  }
  if (vd->vi.bitrate_upper > 0 && vd->vi.bitrate_upper <= 0x7FFFFFFF) {
    gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
        GST_TAG_MAXIMUM_BITRATE, (guint) vd->vi.bitrate_upper, NULL);
    if (!bitrate)
      bitrate = vd->vi.bitrate_upper;
  }
  if (vd->vi.bitrate_lower > 0 && vd->vi.bitrate_lower <= 0x7FFFFFFF) {
    gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
        GST_TAG_MINIMUM_BITRATE, (guint) vd->vi.bitrate_lower, NULL);
    if (!bitrate)
      bitrate = vd->vi.bitrate_lower;
  }
  if (bitrate) {
    gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
        GST_TAG_BITRATE, (guint) bitrate, NULL);
  }

  gst_audio_decoder_merge_tags (GST_AUDIO_DECODER_CAST (vd), list,
      GST_TAG_MERGE_REPLACE);
  gst_tag_list_unref (list);

  return GST_FLOW_OK;
}
예제 #2
0
static GstFlowReturn
vorbis_handle_header_packet (GstVorbisDec * vd, ogg_packet * packet)
{
  GstFlowReturn res;
  gint ret;

  GST_DEBUG_OBJECT (vd, "parsing header packet");

  /* Packetno = 0 if the first byte is exactly 0x01 */
  packet->b_o_s = ((gst_ogg_packet_data (packet))[0] == 0x1) ? 1 : 0;

#ifdef USE_TREMOLO
  if ((ret = vorbis_dsp_headerin (&vd->vi, &vd->vc, packet)))
#else
  if ((ret = vorbis_synthesis_headerin (&vd->vi, &vd->vc, packet)))
#endif
    goto header_read_error;

  switch ((gst_ogg_packet_data (packet))[0]) {
    case 0x01:
      res = vorbis_handle_identification_packet (vd);
      break;
    case 0x03:
      res = vorbis_handle_comment_packet (vd, packet);
      break;
    case 0x05:
      res = vorbis_handle_type_packet (vd);
      break;
    default:
      /* ignore */
      g_warning ("unknown vorbis header packet found");
      res = GST_FLOW_OK;
      break;
  }

  return res;

  /* ERRORS */
header_read_error:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
        (NULL), ("couldn't read header packet (%d)", ret));
    return GST_FLOW_ERROR;
  }
}
예제 #3
0
static GstFlowReturn
vorbis_dec_handle_frame (GstAudioDecoder * dec, GstBuffer * buffer)
{
  ogg_packet *packet;
  ogg_packet_wrapper packet_wrapper;
  GstFlowReturn result = GST_FLOW_OK;
  GstMapInfo map;
  GstVorbisDec *vd = GST_VORBIS_DEC (dec);

  /* no draining etc */
  if (G_UNLIKELY (!buffer))
    return GST_FLOW_OK;

  GST_LOG_OBJECT (vd, "got buffer %p", buffer);
  /* make ogg_packet out of the buffer */
  gst_ogg_packet_wrapper_map (&packet_wrapper, buffer, &map);
  packet = gst_ogg_packet_from_wrapper (&packet_wrapper);
  /* set some more stuff */
  packet->granulepos = -1;
  packet->packetno = 0;         /* we don't care */
  /* EOS does not matter, it is used in vorbis to implement clipping the last
   * block of samples based on the granulepos. We clip based on segments. */
  packet->e_o_s = 0;

  GST_LOG_OBJECT (vd, "decode buffer of size %ld", packet->bytes);

  /* error out on empty header packets, but just skip empty data packets */
  if (G_UNLIKELY (packet->bytes == 0)) {
    if (vd->initialized)
      goto empty_buffer;
    else
      goto empty_header;
  }

  /* switch depending on packet type */
  if ((gst_ogg_packet_data (packet))[0] & 1) {
    if (vd->initialized) {
      GST_WARNING_OBJECT (vd, "Already initialized, so ignoring header packet");
      goto done;
    }
    result = vorbis_handle_header_packet (vd, packet);
    if (result != GST_FLOW_OK)
      goto done;
    /* consumer header packet/frame */
    result = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (vd), NULL, 1);
  } else {
    GstClockTime timestamp, duration;

    timestamp = GST_BUFFER_TIMESTAMP (buffer);
    duration = GST_BUFFER_DURATION (buffer);

    result = vorbis_handle_data_packet (vd, packet, timestamp, duration);
  }

done:
  GST_LOG_OBJECT (vd, "unmap buffer %p", buffer);
  gst_ogg_packet_wrapper_unmap (&packet_wrapper, buffer, &map);

  return result;

empty_buffer:
  {
    /* don't error out here, just ignore the buffer, it's invalid for vorbis
     * but not fatal. */
    GST_WARNING_OBJECT (vd, "empty buffer received, ignoring");
    result = GST_FLOW_OK;
    goto done;
  }

/* ERRORS */
empty_header:
  {
    GST_ELEMENT_ERROR (vd, STREAM, DECODE, (NULL), ("empty header received"));
    result = GST_FLOW_ERROR;
    goto done;
  }
}
예제 #4
0
static GstFlowReturn
vorbis_handle_comment_packet (GstVorbisDec * vd, ogg_packet * packet)
{
  guint bitrate = 0;
  gchar *encoder = NULL;
  GstTagList *list, *old_list;
  GstBuffer *buf;

  GST_DEBUG_OBJECT (vd, "parsing comment packet");

  buf = gst_buffer_new ();
  GST_BUFFER_DATA (buf) = gst_ogg_packet_data (packet);
  GST_BUFFER_SIZE (buf) = gst_ogg_packet_size (packet);

  list =
      gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\003vorbis", 7,
      &encoder);

  old_list = vd->taglist;
  vd->taglist = gst_tag_list_merge (vd->taglist, list, GST_TAG_MERGE_REPLACE);

  if (old_list)
    gst_tag_list_free (old_list);
  gst_tag_list_free (list);
  gst_buffer_unref (buf);

  if (!vd->taglist) {
    GST_ERROR_OBJECT (vd, "couldn't decode comments");
    vd->taglist = gst_tag_list_new ();
  }
  if (encoder) {
    if (encoder[0])
      gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
          GST_TAG_ENCODER, encoder, NULL);
    g_free (encoder);
  }
  gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
      GST_TAG_ENCODER_VERSION, vd->vi.version,
      GST_TAG_AUDIO_CODEC, "Vorbis", NULL);
  if (vd->vi.bitrate_nominal > 0 && vd->vi.bitrate_nominal <= 0x7FFFFFFF) {
    gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
        GST_TAG_NOMINAL_BITRATE, (guint) vd->vi.bitrate_nominal, NULL);
    bitrate = vd->vi.bitrate_nominal;
  }
  if (vd->vi.bitrate_upper > 0 && vd->vi.bitrate_upper <= 0x7FFFFFFF) {
    gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
        GST_TAG_MAXIMUM_BITRATE, (guint) vd->vi.bitrate_upper, NULL);
    if (!bitrate)
      bitrate = vd->vi.bitrate_upper;
  }
  if (vd->vi.bitrate_lower > 0 && vd->vi.bitrate_lower <= 0x7FFFFFFF) {
    gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
        GST_TAG_MINIMUM_BITRATE, (guint) vd->vi.bitrate_lower, NULL);
    if (!bitrate)
      bitrate = vd->vi.bitrate_lower;
  }
  if (bitrate) {
    gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
        GST_TAG_BITRATE, (guint) bitrate, NULL);
  }

  if (vd->initialized) {
    gst_element_found_tags_for_pad (GST_ELEMENT_CAST (vd), vd->srcpad,
        vd->taglist);
    vd->taglist = NULL;
  } else {
    /* Only post them as messages for the time being. *
     * They will be pushed on the pad once the decoder is initialized */
    gst_element_post_message (GST_ELEMENT_CAST (vd),
        gst_message_new_tag (GST_OBJECT (vd), gst_tag_list_copy (vd->taglist)));
  }

  return GST_FLOW_OK;
}