Пример #1
0
static GstFlowReturn
vorbis_dec_push_forward (GstVorbisDec * dec, GstBuffer * buf)
{
  GstFlowReturn result;

  /* clip */
  if (!(buf = gst_audio_buffer_clip (buf, &dec->segment, dec->vi.rate,
              dec->vi.channels * dec->width))) {
    GST_LOG_OBJECT (dec, "clipped buffer");
    return GST_FLOW_OK;
  }

  if (dec->discont) {
    GST_LOG_OBJECT (dec, "setting DISCONT");
    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
    dec->discont = FALSE;
  }

  GST_DEBUG_OBJECT (dec,
      "pushing time %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT,
      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
      GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));

  result = gst_pad_push (dec->srcpad, buf);

  return result;
}
Пример #2
0
static GstFlowReturn
gst_a52dec_push (GstA52Dec * a52dec,
    GstPad * srcpad, int flags, sample_t * samples, GstClockTime timestamp)
{
  GstBuffer *buf;
  int chans, n, c;
  GstFlowReturn result;

  flags &= (A52_CHANNEL_MASK | A52_LFE);
  chans = gst_a52dec_channels (flags, NULL);
  if (!chans) {
    GST_ELEMENT_ERROR (GST_ELEMENT (a52dec), STREAM, DECODE, (NULL),
        ("invalid channel flags: %d", flags));
    return GST_FLOW_ERROR;
  }

  result =
      gst_pad_alloc_buffer_and_set_caps (srcpad, 0,
      256 * chans * (SAMPLE_WIDTH / 8), GST_PAD_CAPS (srcpad), &buf);
  if (result != GST_FLOW_OK)
    return result;

  for (n = 0; n < 256; n++) {
    for (c = 0; c < chans; c++) {
      ((sample_t *) GST_BUFFER_DATA (buf))[n * chans + c] =
          samples[c * 256 + n];
    }
  }
  GST_BUFFER_TIMESTAMP (buf) = timestamp;
  GST_BUFFER_DURATION (buf) = 256 * GST_SECOND / a52dec->sample_rate;

  result = GST_FLOW_OK;
  if ((buf = gst_audio_buffer_clip (buf, &a52dec->segment,
              a52dec->sample_rate, (SAMPLE_WIDTH / 8) * chans))) {
    /* set discont when needed */
    if (a52dec->discont) {
      GST_LOG_OBJECT (a52dec, "marking DISCONT");
      GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
      a52dec->discont = FALSE;
    }

    if (a52dec->segment.rate > 0.0) {
      GST_DEBUG_OBJECT (a52dec,
          "Pushing buffer with ts %" GST_TIME_FORMAT " duration %"
          GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
          GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));

      result = gst_pad_push (srcpad, buf);
    } else {
      /* reverse playback, queue frame till later when we get a discont. */
      GST_DEBUG_OBJECT (a52dec, "queued frame");
      a52dec->queued = g_list_prepend (a52dec->queued, buf);
    }
  }
  return result;
}
Пример #3
0
static GstBuffer *
gst_audio_aggregator_do_clip (GstAggregator * agg,
    GstAggregatorPad * bpad, GstBuffer * buffer)
{
  GstAudioAggregatorPad *pad = GST_AUDIO_AGGREGATOR_PAD (bpad);
  gint rate, bpf;

  rate = GST_AUDIO_INFO_RATE (&pad->info);
  bpf = GST_AUDIO_INFO_BPF (&pad->info);

  GST_OBJECT_LOCK (bpad);
  buffer = gst_audio_buffer_clip (buffer, &bpad->segment, rate, bpf);
  GST_OBJECT_UNLOCK (bpad);

  return buffer;
}
Пример #4
0
static GstFlowReturn
gst_wavpack_dec_chain (GstPad * pad, GstBuffer * buf)
{
    GstWavpackDec *dec;
    GstBuffer *outbuf;
    GstFlowReturn ret = GST_FLOW_OK;
    WavpackHeader wph;
    int32_t decoded, unpacked_size;
    gboolean format_changed;

    dec = GST_WAVPACK_DEC (GST_PAD_PARENT (pad));

    /* check input, we only accept framed input with complete chunks */
    if (GST_BUFFER_SIZE (buf) < sizeof (WavpackHeader))
        goto input_not_framed;

    if (!gst_wavpack_read_header (&wph, GST_BUFFER_DATA (buf)))
        goto invalid_header;

    if (GST_BUFFER_SIZE (buf) < wph.ckSize + 4 * 1 + 4)
        goto input_not_framed;

    if (!(wph.flags & INITIAL_BLOCK))
        goto input_not_framed;

    dec->wv_id.buffer = GST_BUFFER_DATA (buf);
    dec->wv_id.length = GST_BUFFER_SIZE (buf);
    dec->wv_id.position = 0;

    /* create a new wavpack context if there is none yet but if there
     * was already one (i.e. caps were set on the srcpad) check whether
     * the new one has the same caps */
    if (!dec->context) {
        gchar error_msg[80];

        dec->context = WavpackOpenFileInputEx (dec->stream_reader,
                                               &dec->wv_id, NULL, error_msg, OPEN_STREAMING, 0);

        if (!dec->context) {
            GST_WARNING ("Couldn't decode buffer: %s", error_msg);
            dec->error_count++;
            if (dec->error_count <= WAVPACK_DEC_MAX_ERRORS) {
                goto out;               /* just return OK for now */
            } else {
                goto decode_error;
            }
        }
    }

    g_assert (dec->context != NULL);

    dec->error_count = 0;

    format_changed =
        (dec->sample_rate != WavpackGetSampleRate (dec->context)) ||
        (dec->channels != WavpackGetNumChannels (dec->context)) ||
        (dec->depth != WavpackGetBitsPerSample (dec->context)) ||
#ifdef WAVPACK_OLD_API
        (dec->channel_mask != dec->context->config.channel_mask);
#else
        (dec->channel_mask != WavpackGetChannelMask (dec->context));
#endif

    if (!GST_PAD_CAPS (dec->srcpad) || format_changed) {
        GstCaps *caps;
        gint channel_mask;

        dec->sample_rate = WavpackGetSampleRate (dec->context);
        dec->channels = WavpackGetNumChannels (dec->context);
        dec->depth = WavpackGetBitsPerSample (dec->context);

        caps = gst_caps_new_simple ("audio/x-raw-int",
                                    "rate", G_TYPE_INT, dec->sample_rate,
                                    "channels", G_TYPE_INT, dec->channels,
                                    "depth", G_TYPE_INT, dec->depth,
                                    "width", G_TYPE_INT, 32,
                                    "endianness", G_TYPE_INT, G_BYTE_ORDER,
                                    "signed", G_TYPE_BOOLEAN, TRUE, NULL);

#ifdef WAVPACK_OLD_API
        channel_mask = dec->context->config.channel_mask;
#else
        channel_mask = WavpackGetChannelMask (dec->context);
#endif
        if (channel_mask == 0)
            channel_mask = gst_wavpack_get_default_channel_mask (dec->channels);

        dec->channel_mask = channel_mask;

        /* Only set the channel layout for more than two channels
         * otherwise things break unfortunately */
        if (channel_mask != 0 && dec->channels > 2)
            if (!gst_wavpack_set_channel_layout (caps, channel_mask))
                GST_WARNING_OBJECT (dec, "Failed to set channel layout");

        GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps);

        /* should always succeed */
        gst_pad_set_caps (dec->srcpad, caps);
        gst_caps_unref (caps);

        /* send GST_TAG_AUDIO_CODEC and GST_TAG_BITRATE tags before something
         * is decoded or after the format has changed */
        gst_wavpack_dec_post_tags (dec);
    }

    /* alloc output buffer */
    unpacked_size = 4 * wph.block_samples * dec->channels;
    ret = gst_pad_alloc_buffer (dec->srcpad, GST_BUFFER_OFFSET (buf),
                                unpacked_size, GST_PAD_CAPS (dec->srcpad), &outbuf);

    if (ret != GST_FLOW_OK)
        goto out;

    gst_buffer_copy_metadata (outbuf, buf, GST_BUFFER_COPY_TIMESTAMPS);

    /* If we got a DISCONT buffer forward the flag. Nothing else
     * has to be done as libwavpack doesn't store state between
     * Wavpack blocks */
    if (GST_BUFFER_IS_DISCONT (buf) || dec->next_block_index != wph.block_index)
        GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);

    dec->next_block_index = wph.block_index + wph.block_samples;

    /* decode */
    decoded = WavpackUnpackSamples (dec->context,
                                    (int32_t *) GST_BUFFER_DATA (outbuf), wph.block_samples);
    if (decoded != wph.block_samples)
        goto decode_error;

    if ((outbuf = gst_audio_buffer_clip (outbuf, &dec->segment,
                                         dec->sample_rate, 4 * dec->channels))) {
        GST_LOG_OBJECT (dec, "pushing buffer with time %" GST_TIME_FORMAT,
                        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
        ret = gst_pad_push (dec->srcpad, outbuf);
    }

out:

    if (G_UNLIKELY (ret != GST_FLOW_OK)) {
        GST_DEBUG_OBJECT (dec, "flow: %s", gst_flow_get_name (ret));
    }

    gst_buffer_unref (buf);

    return ret;

    /* ERRORS */
input_not_framed:
    {
        GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("Expected framed input"));
        gst_buffer_unref (buf);
        return GST_FLOW_ERROR;
    }
invalid_header:
    {
        GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("Invalid wavpack header"));
        gst_buffer_unref (buf);
        return GST_FLOW_ERROR;
    }
decode_error:
    {
        const gchar *reason = "unknown";

        if (dec->context) {
#ifdef WAVPACK_OLD_API
            reason = dec->context->error_message;
#else
            reason = WavpackGetErrorMessage (dec->context);
#endif
        } else {
            reason = "couldn't create decoder context";
        }
        GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
                           ("Failed to decode wavpack stream: %s", reason));
        gst_buffer_unref (outbuf);
        gst_buffer_unref (buf);
        return GST_FLOW_ERROR;
    }
}
Пример #5
0
static GstFlowReturn
gst_audio_segment_clip_clip_buffer (GstSegmentClip * base, GstBuffer * buffer,
    GstBuffer ** outbuf)
{
  GstAudioSegmentClip *self = GST_AUDIO_SEGMENT_CLIP (base);
  GstSegment *segment = &base->segment;
  GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
  GstClockTime duration = GST_BUFFER_DURATION (buffer);
  guint64 offset = GST_BUFFER_OFFSET (buffer);
  guint64 offset_end = GST_BUFFER_OFFSET_END (buffer);
  guint size = gst_buffer_get_size (buffer);

  if (!self->rate || !self->framesize) {
    GST_ERROR_OBJECT (self, "Not negotiated yet");
    gst_buffer_unref (buffer);
    return GST_FLOW_NOT_NEGOTIATED;
  }

  if (segment->format != GST_FORMAT_DEFAULT &&
      segment->format != GST_FORMAT_TIME) {
    GST_DEBUG_OBJECT (self, "Unsupported segment format %s",
        gst_format_get_name (segment->format));
    *outbuf = buffer;
    return GST_FLOW_OK;
  }

  if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) {
    GST_WARNING_OBJECT (self, "Buffer without valid timestamp");
    *outbuf = buffer;
    return GST_FLOW_OK;
  }

  *outbuf =
      gst_audio_buffer_clip (buffer, segment, self->rate, self->framesize);

  if (!*outbuf) {
    GST_DEBUG_OBJECT (self, "Buffer outside the configured segment");

    /* Now return unexpected if we're before/after the end */
    if (segment->format == GST_FORMAT_TIME) {
      if (segment->rate >= 0) {
        if (segment->stop != -1 && timestamp >= segment->stop)
          return GST_FLOW_EOS;
      } else {
        if (!GST_CLOCK_TIME_IS_VALID (duration))
          duration =
              gst_util_uint64_scale_int (size, GST_SECOND,
              self->framesize * self->rate);

        if (segment->start != -1 && timestamp + duration <= segment->start)
          return GST_FLOW_EOS;
      }
    } else {
      if (segment->rate >= 0) {
        if (segment->stop != -1 && offset != -1 && offset >= segment->stop)
          return GST_FLOW_EOS;
      } else if (offset != -1 || offset_end != -1) {
        if (offset_end == -1)
          offset_end = offset + size / self->framesize;

        if (segment->start != -1 && offset_end <= segment->start)
          return GST_FLOW_EOS;
      }
    }
  }

  return GST_FLOW_OK;
}
static GstFlowReturn
gst_timecodewait_asink_chain (GstPad * pad, GstObject * parent,
    GstBuffer * inbuf)
{
  GstClockTime timestamp;
  GstTimeCodeWait *self = GST_TIMECODEWAIT (parent);
  GstClockTime current_running_time;
  GstClockTime video_running_time = GST_CLOCK_TIME_NONE;
  GstClockTime duration;
  GstClockTime running_time_at_end = GST_CLOCK_TIME_NONE;
  gint asign, vsign = 1, esign = 1;

  timestamp = GST_BUFFER_TIMESTAMP (inbuf);
  if (timestamp == GST_CLOCK_TIME_NONE) {
    gst_buffer_unref (inbuf);
    return GST_FLOW_ERROR;
  }
  g_mutex_lock (&self->mutex);
  self->asegment.position = timestamp;
  asign =
      gst_segment_to_running_time_full (&self->asegment, GST_FORMAT_TIME,
      self->asegment.position, &current_running_time);
  if (asign == 0) {
    g_mutex_unlock (&self->mutex);
    gst_buffer_unref (inbuf);
    GST_ERROR_OBJECT (self, "Could not get current running time");
    return GST_FLOW_ERROR;
  }
  if (self->vsegment.format == GST_FORMAT_TIME) {
    vsign =
        gst_segment_to_running_time_full (&self->vsegment, GST_FORMAT_TIME,
        self->vsegment.position, &video_running_time);
    if (vsign == 0) {
      video_running_time = GST_CLOCK_TIME_NONE;
    }
  }
  while (!(self->video_eos_flag || self->audio_flush_flag
          || self->shutdown_flag) && (video_running_time == GST_CLOCK_TIME_NONE
          || gst_timecodewait_compare_guint64_with_signs (asign,
              current_running_time, vsign, video_running_time) == 1)
      && self->running_time_of_timecode == GST_CLOCK_TIME_NONE) {
    g_cond_wait (&self->cond, &self->mutex);
    vsign =
        gst_segment_to_running_time_full (&self->vsegment, GST_FORMAT_TIME,
        self->vsegment.position, &video_running_time);
    if (vsign == 0) {
      video_running_time = GST_CLOCK_TIME_NONE;
    }
  }
  if (self->audio_flush_flag || self->shutdown_flag) {
    GST_DEBUG_OBJECT (self, "Shutting down, ignoring frame");
    gst_buffer_unref (inbuf);
    return GST_FLOW_FLUSHING;
  }
  duration = GST_BUFFER_DURATION (inbuf);
  if (duration != GST_CLOCK_TIME_NONE) {
    esign =
        gst_segment_to_running_time_full (&self->asegment, GST_FORMAT_TIME,
        self->asegment.position + duration, &running_time_at_end);
    if (esign == 0) {
      g_mutex_unlock (&self->mutex);
      GST_ERROR_OBJECT (self, "Could not get running time at end");
      gst_buffer_unref (inbuf);
      return GST_FLOW_ERROR;
    }
  }
  if (self->running_time_of_timecode == GST_CLOCK_TIME_NONE
      || gst_timecodewait_compare_guint64_with_signs (esign,
          running_time_at_end, 1, self->running_time_of_timecode) == -1) {
    GST_DEBUG_OBJECT (self,
        "Dropped an audio buf at %" GST_TIME_FORMAT " with timecode %"
        GST_TIME_FORMAT " video timecode %" GST_TIME_FORMAT,
        GST_TIME_ARGS (current_running_time),
        GST_TIME_ARGS (self->running_time_of_timecode),
        GST_TIME_ARGS (video_running_time));
    gst_buffer_unref (inbuf);
    inbuf = NULL;
  } else if (current_running_time < self->running_time_of_timecode
      && running_time_at_end > self->running_time_of_timecode) {
    GstSegment asegment2 = self->asegment;

    gst_segment_set_running_time (&asegment2, GST_FORMAT_TIME,
        self->running_time_of_timecode);
    inbuf =
        gst_audio_buffer_clip (inbuf, &asegment2, self->ainfo.rate,
        self->ainfo.bpf);
  }
  g_mutex_unlock (&self->mutex);
  if (inbuf)
    return gst_pad_push (self->asrcpad, inbuf);
  else
    return GST_FLOW_OK;
}
Пример #7
0
void test_buffer_clipping_samples()
{
  GstSegment s;
  GstBuffer *buf;
  GstBuffer *ret;
  guint8 *data;
  
        	xmlfile = "test_buffer_clipping_samples";
  std_log(LOG_FILENAME_LINE, "Test Started test_buffer_clipping_samples");

  /* Clip start and end */
  buf = gst_buffer_new ();
  data = (guint8 *) g_malloc (1000);
  GST_BUFFER_SIZE (buf) = 1000;
  GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;

  gst_segment_init (&s, GST_FORMAT_DEFAULT);
  gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 400,
      800, 400);

  GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND;
  GST_BUFFER_DURATION (buf) = 10 * GST_SECOND;
  GST_BUFFER_OFFSET (buf) = 200;
  GST_BUFFER_OFFSET_END (buf) = 1200;

  ret = gst_audio_buffer_clip (buf, &s, 100, 1);
  fail_unless (ret != NULL);

  fail_unless (GST_BUFFER_TIMESTAMP (ret) == 4 * GST_SECOND);
  fail_unless (GST_BUFFER_DURATION (ret) == 4 * GST_SECOND);
  fail_unless (GST_BUFFER_OFFSET (ret) == 400);
  fail_unless (GST_BUFFER_OFFSET_END (ret) == 800);
  fail_unless (GST_BUFFER_DATA (ret) == data + 200);
  fail_unless (GST_BUFFER_SIZE (ret) == 400);

  gst_buffer_unref (ret);

  /* Clip only start */
  buf = gst_buffer_new ();
  data = (guint8 *) g_malloc (1000);
  GST_BUFFER_SIZE (buf) = 1000;
  GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;

  gst_segment_init (&s, GST_FORMAT_DEFAULT);
  gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 400,
      1200, 400);

  GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND;
  GST_BUFFER_DURATION (buf) = 10 * GST_SECOND;
  GST_BUFFER_OFFSET (buf) = 200;
  GST_BUFFER_OFFSET_END (buf) = 1200;

  ret = gst_audio_buffer_clip (buf, &s, 100, 1);
  fail_unless (ret != NULL);

  fail_unless (GST_BUFFER_TIMESTAMP (ret) == 4 * GST_SECOND);
  fail_unless (GST_BUFFER_DURATION (ret) == 8 * GST_SECOND);
  fail_unless (GST_BUFFER_OFFSET (ret) == 400);
  fail_unless (GST_BUFFER_OFFSET_END (ret) == 1200);
  fail_unless (GST_BUFFER_DATA (ret) == data + 200);
  fail_unless (GST_BUFFER_SIZE (ret) == 800);

  gst_buffer_unref (ret);

  /* Clip only stop */
  buf = gst_buffer_new ();
  data = (guint8 *) g_malloc (1000);
  GST_BUFFER_SIZE (buf) = 1000;
  GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;

  gst_segment_init (&s, GST_FORMAT_DEFAULT);
  gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 200,
      1000, 200);

  GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND;
  GST_BUFFER_DURATION (buf) = 10 * GST_SECOND;
  GST_BUFFER_OFFSET (buf) = 200;
  GST_BUFFER_OFFSET_END (buf) = 1200;

  ret = gst_audio_buffer_clip (buf, &s, 100, 1);
  fail_unless (ret != NULL);

  fail_unless (GST_BUFFER_TIMESTAMP (ret) == 2 * GST_SECOND);
  fail_unless (GST_BUFFER_DURATION (ret) == 8 * GST_SECOND);
  fail_unless (GST_BUFFER_OFFSET (ret) == 200);
  fail_unless (GST_BUFFER_OFFSET_END (ret) == 1000);
  fail_unless (GST_BUFFER_DATA (ret) == data);
  fail_unless (GST_BUFFER_SIZE (ret) == 800);

  gst_buffer_unref (ret);

  /* Buffer outside segment */
  buf = gst_buffer_new ();
  data = (guint8 *) g_malloc (1000);
  GST_BUFFER_SIZE (buf) = 1000;
  GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;

  gst_segment_init (&s, GST_FORMAT_DEFAULT);
  gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 1200,
      2000, 1200);

  GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND;
  GST_BUFFER_DURATION (buf) = 10 * GST_SECOND;
  GST_BUFFER_OFFSET (buf) = 200;
  GST_BUFFER_OFFSET_END (buf) = 1200;

  ret = gst_audio_buffer_clip (buf, &s, 100, 1);
  fail_unless (ret == NULL);

  /* Clip start and end but don't touch duration and offset_end */
  buf = gst_buffer_new ();
  data = (guint8 *) g_malloc (1000);
  GST_BUFFER_SIZE (buf) = 1000;
  GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;

  gst_segment_init (&s, GST_FORMAT_DEFAULT);
  gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 400,
      800, 400);

  GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND;
  GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE;
  GST_BUFFER_OFFSET (buf) = 200;
  GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE;

  ret = gst_audio_buffer_clip (buf, &s, 100, 1);
  fail_unless (ret != NULL);

  fail_unless (GST_BUFFER_TIMESTAMP (ret) == 4 * GST_SECOND);
  fail_unless (GST_BUFFER_DURATION (ret) == GST_CLOCK_TIME_NONE);
  fail_unless (GST_BUFFER_OFFSET (ret) == 400);
  fail_unless (GST_BUFFER_OFFSET_END (ret) == GST_BUFFER_OFFSET_NONE);
  fail_unless (GST_BUFFER_DATA (ret) == data + 200);
  fail_unless (GST_BUFFER_SIZE (ret) == 400);

  gst_buffer_unref (ret);

  /* If the buffer has no offset it should assert()
   * FIXME: check if return value is the same as the input buffer.
   *        probably can't be done because the assert() does a SIGABRT.
   */
  buf = gst_buffer_new ();
  data = (guint8 *) g_malloc (1000);
  GST_BUFFER_SIZE (buf) = 1000;
  GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;

  gst_segment_init (&s, GST_FORMAT_DEFAULT);
  gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 0, 10, 0);

  GST_BUFFER_TIMESTAMP (buf) = 0 * GST_SECOND;
  GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE;
  GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE;
  GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE;

  ASSERT_CRITICAL (ret = gst_audio_buffer_clip (buf, &s, 100, 1));

  gst_buffer_unref (buf);
  
      std_log(LOG_FILENAME_LINE, "Test Successful");
  create_xml(0);
}
Пример #8
0
static GstFlowReturn
gst_live_live_adder_chain (GstPad * pad, GstBuffer * buffer)
{
    GstLiveAdder *adder = GST_LIVE_ADDER (gst_pad_get_parent_element (pad));
    GstLiveAdderPadPrivate *padprivate = NULL;
    GstFlowReturn ret = GST_FLOW_OK;
    GList *item = NULL;
    GstClockTime skip = 0;
    gint64 drift = 0;             /* Positive if new buffer after old buffer */

    GST_OBJECT_LOCK (adder);

    ret = adder->srcresult;

    GST_DEBUG ("Incoming buffer time:%" GST_TIME_FORMAT " duration:%"
               GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
               GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));

    if (ret != GST_FLOW_OK) {
        GST_DEBUG_OBJECT (adder, "Passing non-ok result from src: %s",
                          gst_flow_get_name (ret));
        gst_buffer_unref (buffer);
        goto out;
    }

    padprivate = gst_pad_get_element_private (pad);

    if (!padprivate) {
        ret = GST_FLOW_NOT_LINKED;
        gst_buffer_unref (buffer);
        goto out;
    }

    if (padprivate->eos) {
        GST_DEBUG_OBJECT (adder, "Received buffer after EOS");
        ret = GST_FLOW_UNEXPECTED;
        gst_buffer_unref (buffer);
        goto out;
    }

    if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
        goto invalid_timestamp;

    if (padprivate->segment.format == GST_FORMAT_UNDEFINED) {
        GST_WARNING_OBJECT (adder, "No new-segment received,"
                            " initializing segment with time 0..-1");
        gst_segment_init (&padprivate->segment, GST_FORMAT_TIME);
        gst_segment_set_newsegment (&padprivate->segment,
                                    FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0);
    }

    if (padprivate->segment.format != GST_FORMAT_TIME)
        goto invalid_segment;

    buffer = gst_buffer_make_metadata_writable (buffer);

    drift = GST_BUFFER_TIMESTAMP (buffer) - padprivate->expected_timestamp;

    /* Just see if we receive invalid timestamp/durations */
    if (GST_CLOCK_TIME_IS_VALID (padprivate->expected_timestamp) &&
            !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT) &&
            (drift != 0)) {
        GST_LOG_OBJECT (adder,
                        "Timestamp discontinuity without the DISCONT flag set"
                        " (expected %" GST_TIME_FORMAT ", got %" GST_TIME_FORMAT
                        " drift:%" G_GINT64_FORMAT "ms)",
                        GST_TIME_ARGS (padprivate->expected_timestamp),
                        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), drift / GST_MSECOND);

        /* We accept drifts of 10ms */
        if (ABS (drift) < (10 * GST_MSECOND)) {
            GST_DEBUG ("Correcting minor drift");
            GST_BUFFER_TIMESTAMP (buffer) = padprivate->expected_timestamp;
        }
    }


    /* If there is no duration, lets set one */
    if (!GST_BUFFER_DURATION_IS_VALID (buffer)) {
        GST_BUFFER_DURATION (buffer) =
            gst_audio_duration_from_pad_buffer (pad, buffer);
        padprivate->expected_timestamp = GST_CLOCK_TIME_NONE;
    } else {
        padprivate->expected_timestamp = GST_BUFFER_TIMESTAMP (buffer) +
                                         GST_BUFFER_DURATION (buffer);
    }


    /*
     * Lets clip the buffer to the segment (so we don't have to worry about
     * cliping afterwards).
     * This should also guarantee us that we'll have valid timestamps and
     * durations afterwards
     */

    buffer = gst_audio_buffer_clip (buffer, &padprivate->segment, adder->rate,
                                    adder->bps);

    /* buffer can be NULL if it's completely outside of the segment */
    if (!buffer) {
        GST_DEBUG ("Buffer completely outside of configured segment, dropping it");
        goto out;
    }

    /*
     * Make sure all incoming buffers share the same timestamping
     */
    GST_BUFFER_TIMESTAMP (buffer) =
        gst_segment_to_running_time (&padprivate->segment,
                                     padprivate->segment.format, GST_BUFFER_TIMESTAMP (buffer));


    if (GST_CLOCK_TIME_IS_VALID (adder->next_timestamp) &&
            GST_BUFFER_TIMESTAMP (buffer) < adder->next_timestamp) {
        if (GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) <
                adder->next_timestamp) {
            GST_DEBUG_OBJECT (adder, "Buffer is late, dropping (ts: %" GST_TIME_FORMAT
                              " duration: %" GST_TIME_FORMAT ")",
                              GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
                              GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
            gst_buffer_unref (buffer);
            goto out;
        } else {
            skip = adder->next_timestamp - GST_BUFFER_TIMESTAMP (buffer);
            GST_DEBUG_OBJECT (adder, "Buffer is partially late, skipping %"
                              GST_TIME_FORMAT, GST_TIME_ARGS (skip));
        }
    }

    /* If our new buffer's head is higher than the queue's head, lets wake up,
     * we may not have to wait for as long
     */
    if (adder->clock_id &&
            g_queue_peek_head (adder->buffers) != NULL &&
            GST_BUFFER_TIMESTAMP (buffer) + skip <
            GST_BUFFER_TIMESTAMP (g_queue_peek_head (adder->buffers)))
        gst_clock_id_unschedule (adder->clock_id);

    for (item = g_queue_peek_head_link (adder->buffers);
            item; item = g_list_next (item)) {
        GstBuffer *oldbuffer = item->data;
        GstClockTime old_skip = 0;
        GstClockTime mix_duration = 0;
        GstClockTime mix_start = 0;
        GstClockTime mix_end = 0;

        /* We haven't reached our place yet */
        if (GST_BUFFER_TIMESTAMP (buffer) + skip >=
                GST_BUFFER_TIMESTAMP (oldbuffer) + GST_BUFFER_DURATION (oldbuffer))
            continue;

        /* We're past our place, lets insert ouselves here */
        if (GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) <=
                GST_BUFFER_TIMESTAMP (oldbuffer))
            break;

        /* if we reach this spot, we have overlap, so we must mix */

        /* First make a subbuffer with the non-overlapping part */
        if (GST_BUFFER_TIMESTAMP (buffer) + skip < GST_BUFFER_TIMESTAMP (oldbuffer)) {
            GstBuffer *subbuffer = NULL;
            GstClockTime subbuffer_duration = GST_BUFFER_TIMESTAMP (oldbuffer) -
                                              (GST_BUFFER_TIMESTAMP (buffer) + skip);

            subbuffer = gst_buffer_create_sub (buffer,
                                               gst_live_adder_length_from_duration (adder, skip),
                                               gst_live_adder_length_from_duration (adder, subbuffer_duration));

            GST_BUFFER_TIMESTAMP (subbuffer) = GST_BUFFER_TIMESTAMP (buffer) + skip;
            GST_BUFFER_DURATION (subbuffer) = subbuffer_duration;

            skip += subbuffer_duration;

            g_queue_insert_before (adder->buffers, item, subbuffer);
        }

        /* Now we are on the overlapping part */
        oldbuffer = gst_buffer_make_writable (oldbuffer);
        item->data = oldbuffer;

        old_skip = GST_BUFFER_TIMESTAMP (buffer) + skip -
                   GST_BUFFER_TIMESTAMP (oldbuffer);

        mix_start = GST_BUFFER_TIMESTAMP (oldbuffer) + old_skip;

        if (GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) <
                GST_BUFFER_TIMESTAMP (oldbuffer) + GST_BUFFER_DURATION (oldbuffer))
            mix_end = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer);
        else
            mix_end = GST_BUFFER_TIMESTAMP (oldbuffer) +
                      GST_BUFFER_DURATION (oldbuffer);

        mix_duration = mix_end - mix_start;

        adder->func (GST_BUFFER_DATA (oldbuffer) +
                     gst_live_adder_length_from_duration (adder, old_skip),
                     GST_BUFFER_DATA (buffer) +
                     gst_live_adder_length_from_duration (adder, skip),
                     gst_live_adder_length_from_duration (adder, mix_duration));

        skip += mix_duration;
    }

    g_cond_broadcast (adder->not_empty_cond);

    if (skip == GST_BUFFER_DURATION (buffer)) {
        gst_buffer_unref (buffer);
    } else {
        if (skip) {
            GstClockTime subbuffer_duration = GST_BUFFER_DURATION (buffer) - skip;
            GstClockTime subbuffer_ts = GST_BUFFER_TIMESTAMP (buffer) + skip;
            GstBuffer *new_buffer = gst_buffer_create_sub (buffer,
                                    gst_live_adder_length_from_duration (adder, skip),
                                    gst_live_adder_length_from_duration (adder, subbuffer_duration));
            gst_buffer_unref (buffer);
            buffer = new_buffer;
            GST_BUFFER_TIMESTAMP (buffer) = subbuffer_ts;
            GST_BUFFER_DURATION (buffer) = subbuffer_duration;
        }

        if (item)
            g_queue_insert_before (adder->buffers, item, buffer);
        else
            g_queue_push_tail (adder->buffers, buffer);
    }

out:

    GST_OBJECT_UNLOCK (adder);
    gst_object_unref (adder);

    return ret;

invalid_timestamp:

    GST_OBJECT_UNLOCK (adder);
    gst_buffer_unref (buffer);
    GST_ELEMENT_ERROR (adder, STREAM, FAILED,
                       ("Buffer without a valid timestamp received"),
                       ("Invalid timestamp received on buffer"));

    return GST_FLOW_ERROR;

invalid_segment:
    {
        const gchar *format = gst_format_get_name (padprivate->segment.format);
        GST_OBJECT_UNLOCK (adder);
        gst_buffer_unref (buffer);
        GST_ELEMENT_ERROR (adder, STREAM, FAILED,
                           ("This element only supports TIME segments, received other type"),
                           ("Received a segment of type %s, only support time segment", format));

        return GST_FLOW_ERROR;
    }

}