gboolean
gst_opus_header_is_id_header (GstBuffer * buf)
{
  gsize size = gst_buffer_get_size (buf);
  guint8 *data = NULL;
  guint8 version, channels, channel_mapping_family, n_streams, n_stereo_streams;
  gboolean ret = FALSE;
  GstMapInfo map;

  if (size < 19)
    goto beach;
  if (!gst_opus_header_is_header (buf, "OpusHead", 8))
    goto beach;

  gst_buffer_map (buf, &map, GST_MAP_READ);
  data = map.data;
  size = map.size;

  version = data[8];
  if (version >= 0x0f)          /* major version >=0 is what we grok */
    goto beach;

  channels = data[9];

  if (channels == 0)
    goto beach;

  channel_mapping_family = data[18];

  if (channel_mapping_family == 0) {
    if (channels > 2)
      goto beach;
  } else {
    channels = data[9];
    if (size < 21 + channels)
      goto beach;
    n_streams = data[19];
    n_stereo_streams = data[20];
    if (n_streams == 0)
      goto beach;
    if (n_stereo_streams > n_streams)
      goto beach;
    if (n_streams + n_stereo_streams > 255)
      goto beach;
  }
  ret = TRUE;

beach:
  if (data)
    gst_buffer_unmap (buf, &map);
  return ret;
}
示例#2
0
static GstFlowReturn
gst_opus_dec_handle_frame (GstAudioDecoder * adec, GstBuffer * buf)
{
  GstFlowReturn res;
  GstOpusDec *dec;

  /* no fancy draining */
  if (G_UNLIKELY (!buf))
    return GST_FLOW_OK;

  dec = GST_OPUS_DEC (adec);
  GST_LOG_OBJECT (dec,
      "Got buffer ts %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT,
      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
      GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));

  /* If we have the streamheader and vorbiscomment from the caps already
   * ignore them here */
  if (dec->streamheader && dec->vorbiscomment) {
    if (memcmp_buffers (dec->streamheader, buf)) {
      GST_DEBUG_OBJECT (dec, "found streamheader");
      gst_audio_decoder_finish_frame (adec, NULL, 1);
      res = GST_FLOW_OK;
    } else if (memcmp_buffers (dec->vorbiscomment, buf)) {
      GST_DEBUG_OBJECT (dec, "found vorbiscomments");
      gst_audio_decoder_finish_frame (adec, NULL, 1);
      res = GST_FLOW_OK;
    } else {
      res = opus_dec_chain_parse_data (dec, buf);
    }
  } else {
    /* Otherwise fall back to packet counting and assume that the
     * first two packets might be the headers, checking magic. */
    switch (dec->packetno) {
      case 0:
        if (gst_opus_header_is_header (buf, "OpusHead", 8)) {
          GST_DEBUG_OBJECT (dec, "found streamheader");
          res = gst_opus_dec_parse_header (dec, buf);
          gst_audio_decoder_finish_frame (adec, NULL, 1);
        } else {
          res = opus_dec_chain_parse_data (dec, buf);
        }
        break;
      case 1:
        if (gst_opus_header_is_header (buf, "OpusTags", 8)) {
          GST_DEBUG_OBJECT (dec, "counted vorbiscomments");
          res = gst_opus_dec_parse_comments (dec, buf);
          gst_audio_decoder_finish_frame (adec, NULL, 1);
        } else {
          res = opus_dec_chain_parse_data (dec, buf);
        }
        break;
      default:
      {
        res = opus_dec_chain_parse_data (dec, buf);
        break;
      }
    }
  }

  dec->packetno++;

  return res;
}
gboolean
gst_opus_header_is_comment_header (GstBuffer * buf)
{
  return gst_opus_header_is_header (buf, "OpusTags", 8);
}