예제 #1
0
static GstFlowReturn
gst_flac_dec_handle_frame (GstAudioDecoder * audio_dec, GstBuffer * buf)
{
  GstFlacDec *dec;

  dec = GST_FLAC_DEC (audio_dec);

  /* drain remaining data? */
  if (G_UNLIKELY (buf == NULL)) {
    gst_flac_dec_flush (audio_dec, FALSE);
    return GST_FLOW_OK;
  }

  GST_LOG_OBJECT (dec, "frame: ts %" GST_TIME_FORMAT ", flags 0x%04x, "
      "%" G_GSIZE_FORMAT " bytes", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
      GST_BUFFER_FLAGS (buf), gst_buffer_get_size (buf));

  /* drop any in-stream headers, we've processed those in set_format already */
  if (G_UNLIKELY (!dec->got_headers)) {
    gboolean got_audio_frame;
    GstMapInfo map;

    /* check if this is a flac audio frame (rather than a header or junk) */
    gst_buffer_map (buf, &map, GST_MAP_READ);
    got_audio_frame =
        gst_flac_dec_scan_got_frame (dec, map.data, map.size, NULL);
    gst_buffer_unmap (buf, &map);

    if (!got_audio_frame) {
      GST_INFO_OBJECT (dec, "dropping in-stream header, %" G_GSIZE_FORMAT " "
          "bytes", map.size);
      gst_audio_decoder_finish_frame (audio_dec, NULL, 1);
      return GST_FLOW_OK;
    }

    GST_INFO_OBJECT (dec, "first audio frame, got all in-stream headers now");
    dec->got_headers = TRUE;
  }

  gst_adapter_push (dec->adapter, gst_buffer_ref (buf));
  buf = NULL;

  dec->last_flow = GST_FLOW_OK;

  /* framed - there should always be enough data to decode something */
  GST_LOG_OBJECT (dec, "%" G_GSIZE_FORMAT " bytes available",
      gst_adapter_available (dec->adapter));

  if (!FLAC__stream_decoder_process_single (dec->decoder)) {
    GST_INFO_OBJECT (dec, "process_single failed");
  }

  return dec->last_flow;
}
예제 #2
0
static GstFlowReturn
theora_parse_drain_queue_prematurely (GstTheoraParse * parse)
{
  GstFlowReturn ret = GST_FLOW_OK;

  /* got an EOS event, make sure to push out any buffers that were in the queue
   * -- won't normally be the case, but this catches the
   * didn't-get-a-granulepos-on-the-last-packet case. Assuming a continuous
   * stream. */

  GST_DEBUG_OBJECT (parse, "got EOS, draining queue");

  /* if we get an eos before pushing the streamheaders, drain our events before
   * eos */
  theora_parse_drain_event_queue (parse);

  while (!g_queue_is_empty (parse->buffer_queue)) {
    GstBuffer *buf;

    buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue));

    parse->prev_frame++;

    if (is_keyframe (buf))
      /* we have a keyframe */
      parse->prev_keyframe = parse->prev_frame;
    else
      GST_BUFFER_FLAGS (buf) |= GST_BUFFER_FLAG_DELTA_UNIT;

    if (parse->prev_keyframe < 0) {
      if (GST_BUFFER_OFFSET_END_IS_VALID (buf)) {
        parse_granulepos (parse, GST_BUFFER_OFFSET_END (buf),
            &parse->prev_keyframe, NULL);
      } else {
        /* No previous keyframe known; can't extract one from this frame. That
         * means we can't do any valid output for this frame, just continue to
         * the next frame.
         */
        gst_buffer_unref (buf);
        continue;
      }
    }

    ret = theora_parse_push_buffer (parse, buf, parse->prev_keyframe,
        parse->prev_frame);

    if (ret != GST_FLOW_OK)
      goto done;
  }

done:
  return ret;
}
static void
default_reset_buffer (GstBufferPool * pool, GstBuffer * buffer)
{
  GST_BUFFER_FLAGS (buffer) = 0;

  GST_BUFFER_PTS (buffer) = GST_CLOCK_TIME_NONE;
  GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE;
  GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
  GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE;
  GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE;

  /* remove all metadata without the POOLED flag */
  gst_buffer_foreach_meta (buffer, remove_meta_unpooled, pool);
}
예제 #4
0
static void
gst_identity_update_last_message_for_buffer (GstIdentity * identity,
    const gchar * action, GstBuffer * buf, gsize size)
{
  gchar dts_str[64], pts_str[64], dur_str[64];
  gchar flag_str[100];

  GST_OBJECT_LOCK (identity);

  {
    const char *flag_list[] = {
      "", "", "", "", "live", "decode-only", "discont", "resync", "corrupted",
      "marker", "header", "gap", "droppable", "delta-unit", "tag-memory",
      "FIXME"
    };
    int i;
    char *end = flag_str;
    end[0] = '\0';
    for (i = 0; i < G_N_ELEMENTS (flag_list); i++) {
      if (GST_MINI_OBJECT_CAST (buf)->flags & (1 << i)) {
        strcpy (end, flag_list[i]);
        end += strlen (end);
        end[0] = ' ';
        end[1] = '\0';
        end++;
      }
    }
  }

  g_free (identity->last_message);
  identity->last_message = g_strdup_printf ("%s   ******* (%s:%s) "
      "(%" G_GSIZE_FORMAT " bytes, dts: %s, pts:%s, duration: %s, offset: %"
      G_GINT64_FORMAT ", " "offset_end: % " G_GINT64_FORMAT
      ", flags: %08x %s) %p", action,
      GST_DEBUG_PAD_NAME (GST_BASE_TRANSFORM_CAST (identity)->sinkpad), size,
      print_pretty_time (dts_str, sizeof (dts_str), GST_BUFFER_DTS (buf)),
      print_pretty_time (pts_str, sizeof (pts_str), GST_BUFFER_PTS (buf)),
      print_pretty_time (dur_str, sizeof (dur_str), GST_BUFFER_DURATION (buf)),
      GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf),
      GST_BUFFER_FLAGS (buf), flag_str, buf);

  GST_OBJECT_UNLOCK (identity);

  gst_identity_notify_last_message (identity);
}
예제 #5
0
static void
do_buffer_stats (GstStatsTracer * self, GstPad * this_pad,
    GstPadStats * this_pad_stats, GstPad * that_pad,
    GstPadStats * that_pad_stats, GstBuffer * buf, GstClockTime elapsed)
{
  GstElement *this_elem = get_real_pad_parent (this_pad);
  GstElementStats *this_elem_stats = get_element_stats (self, this_elem);
  GstElement *that_elem = get_real_pad_parent (that_pad);
  GstElementStats *that_elem_stats = get_element_stats (self, that_elem);
  GstClockTime pts = GST_BUFFER_PTS (buf);
  GstClockTime dts = GST_BUFFER_DTS (buf);
  GstClockTime dur = GST_BUFFER_DURATION (buf);

  gst_tracer_record_log (tr_buffer, (guint64) (guintptr) g_thread_self (),
      elapsed, this_pad_stats->index, this_elem_stats->index,
      that_pad_stats->index, that_elem_stats->index, gst_buffer_get_size (buf),
      GST_CLOCK_TIME_IS_VALID (pts), pts, GST_CLOCK_TIME_IS_VALID (dts), dts,
      GST_CLOCK_TIME_IS_VALID (dur), dur, GST_BUFFER_FLAGS (buf));
}
static void
gst_identity_update_last_message_for_buffer (GstIdentity * identity,
    const gchar * action, GstBuffer * buf)
{
  gchar ts_str[64], dur_str[64];

  GST_OBJECT_LOCK (identity);

  g_free (identity->last_message);
  identity->last_message = g_strdup_printf ("%s   ******* (%s:%s)i "
      "(%u bytes, timestamp: %s, duration: %s, offset: %" G_GINT64_FORMAT ", "
      "offset_end: % " G_GINT64_FORMAT ", flags: %d) %p", action,
      GST_DEBUG_PAD_NAME (GST_BASE_TRANSFORM_CAST (identity)->sinkpad),
      GST_BUFFER_SIZE (buf),
      print_pretty_time (ts_str, sizeof (ts_str), GST_BUFFER_TIMESTAMP (buf)),
      print_pretty_time (dur_str, sizeof (dur_str), GST_BUFFER_DURATION (buf)),
      GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf),
      GST_BUFFER_FLAGS (buf), buf);

  GST_OBJECT_UNLOCK (identity);

  gst_identity_notify_last_message (identity);
}
예제 #7
0
static void
gst_compare_meta (GstCompare * comp, GstBuffer * buf1, GstCaps * caps1,
    GstBuffer * buf2, GstCaps * caps2)
{
  gint flags = 0;

  if (comp->meta & GST_BUFFER_COPY_FLAGS) {
    if (GST_BUFFER_FLAGS (buf1) != GST_BUFFER_FLAGS (buf2)) {
      flags |= GST_BUFFER_COPY_FLAGS;
      GST_DEBUG_OBJECT (comp, "flags %d != flags %d", GST_BUFFER_FLAGS (buf1),
          GST_BUFFER_FLAGS (buf2));
    }
  }
  if (comp->meta & GST_BUFFER_COPY_TIMESTAMPS) {
    if (GST_BUFFER_TIMESTAMP (buf1) != GST_BUFFER_TIMESTAMP (buf2)) {
      flags |= GST_BUFFER_COPY_TIMESTAMPS;
      GST_DEBUG_OBJECT (comp,
          "ts %" GST_TIME_FORMAT " != ts %" GST_TIME_FORMAT,
          GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf1)),
          GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf2)));
    }
    if (GST_BUFFER_DURATION (buf1) != GST_BUFFER_DURATION (buf2)) {
      flags |= GST_BUFFER_COPY_TIMESTAMPS;
      GST_DEBUG_OBJECT (comp,
          "dur %" GST_TIME_FORMAT " != dur %" GST_TIME_FORMAT,
          GST_TIME_ARGS (GST_BUFFER_DURATION (buf1)),
          GST_TIME_ARGS (GST_BUFFER_DURATION (buf2)));
    }
    if (comp->offset_ts) {
      if (GST_BUFFER_OFFSET (buf1) != GST_BUFFER_OFFSET (buf2)) {
        flags |= GST_BUFFER_COPY_TIMESTAMPS;
        GST_DEBUG_OBJECT (comp,
            "offset %" G_GINT64_FORMAT " != offset %" G_GINT64_FORMAT,
            GST_BUFFER_OFFSET (buf1), GST_BUFFER_OFFSET (buf2));
      }
      if (GST_BUFFER_OFFSET_END (buf1) != GST_BUFFER_OFFSET_END (buf2)) {
        flags |= GST_BUFFER_COPY_TIMESTAMPS;
        GST_DEBUG_OBJECT (comp,
            "offset_end %" G_GINT64_FORMAT " != offset_end %" G_GINT64_FORMAT,
            GST_BUFFER_OFFSET_END (buf1), GST_BUFFER_OFFSET_END (buf2));
      }
    }
  }
#if 0
  /* FIXME ?? */
  if (comp->meta & GST_BUFFER_COPY_CAPS) {
    if (!gst_caps_is_equal (caps1, caps2)) {
      flags |= GST_BUFFER_COPY_CAPS;
      GST_DEBUG_OBJECT (comp,
          "caps %" GST_PTR_FORMAT " != caps %" GST_PTR_FORMAT, caps1, caps2);
    }
  }
#endif

  /* signal mismatch by debug and message */
  if (flags) {
    GST_WARNING_OBJECT (comp, "buffers %p and %p failed metadata match %d",
        buf1, buf2, flags);

    gst_element_post_message (GST_ELEMENT (comp),
        gst_message_new_element (GST_OBJECT (comp),
            gst_structure_new ("delta", "meta", G_TYPE_INT, flags, NULL)));
  }
}
예제 #8
0
static GstFlowReturn
gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
{
  GstFlowReturn ret = GST_FLOW_OK;
  GstIdentity *identity = GST_IDENTITY (trans);
  GstClockTime runtimestamp = G_GINT64_CONSTANT (0);

  if (identity->check_perfect)
    gst_identity_check_perfect (identity, buf);
  if (identity->check_imperfect_timestamp)
    gst_identity_check_imperfect_timestamp (identity, buf);
  if (identity->check_imperfect_offset)
    gst_identity_check_imperfect_offset (identity, buf);

  /* update prev values */
  identity->prev_timestamp = GST_BUFFER_TIMESTAMP (buf);
  identity->prev_duration = GST_BUFFER_DURATION (buf);
  identity->prev_offset_end = GST_BUFFER_OFFSET_END (buf);
  identity->prev_offset = GST_BUFFER_OFFSET (buf);

  if (identity->error_after >= 0) {
    identity->error_after--;
    if (identity->error_after == 0) {
      GST_ELEMENT_ERROR (identity, CORE, FAILED,
          (_("Failed after iterations as requested.")), (NULL));
      return GST_FLOW_ERROR;
    }
  }

  if (identity->drop_probability > 0.0) {
    if ((gfloat) (1.0 * rand () / (RAND_MAX)) < identity->drop_probability) {
      if (!identity->silent) {
        GST_OBJECT_LOCK (identity);
        g_free (identity->last_message);
        identity->last_message =
            g_strdup_printf
            ("dropping   ******* (%s:%s)i (%d bytes, timestamp: %"
            GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %"
            G_GINT64_FORMAT ", offset_end: % " G_GINT64_FORMAT
            ", flags: %d) %p", GST_DEBUG_PAD_NAME (trans->sinkpad),
            GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
            GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf),
            GST_BUFFER_OFFSET_END (buf), GST_BUFFER_FLAGS (buf), buf);
        GST_OBJECT_UNLOCK (identity);
        g_object_notify (G_OBJECT (identity), "last-message");
      }
      /* return DROPPED to basetransform. */
      return GST_BASE_TRANSFORM_FLOW_DROPPED;
    }
  }

  if (identity->dump) {
    gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
  }

  if (!identity->silent) {
    GST_OBJECT_LOCK (identity);
    g_free (identity->last_message);
    identity->last_message =
        g_strdup_printf ("chain   ******* (%s:%s)i (%d bytes, timestamp: %"
        GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %"
        G_GINT64_FORMAT ", offset_end: % " G_GINT64_FORMAT ", flags: %d) %p",
        GST_DEBUG_PAD_NAME (trans->sinkpad), GST_BUFFER_SIZE (buf),
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
        GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
        GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf),
        GST_BUFFER_FLAGS (buf), buf);
    GST_OBJECT_UNLOCK (identity);
    g_object_notify (G_OBJECT (identity), "last-message");
  }

  if (identity->datarate > 0) {
    GstClockTime time = gst_util_uint64_scale_int (identity->offset,
        GST_SECOND, identity->datarate);

    GST_BUFFER_TIMESTAMP (buf) = time;
    GST_BUFFER_DURATION (buf) =
        GST_BUFFER_SIZE (buf) * GST_SECOND / identity->datarate;
  }

  if (identity->signal_handoffs)
    g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
        buf);

  if (trans->segment.format == GST_FORMAT_TIME)
    runtimestamp = gst_segment_to_running_time (&trans->segment,
        GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf));

  if ((identity->sync) && (trans->segment.format == GST_FORMAT_TIME)) {
    GstClock *clock;

    GST_OBJECT_LOCK (identity);
    if ((clock = GST_ELEMENT (identity)->clock)) {
      GstClockReturn cret;
      GstClockTime timestamp;

      timestamp = runtimestamp + GST_ELEMENT (identity)->base_time;

      /* save id if we need to unlock */
      /* FIXME: actually unlock this somewhere in the state changes */
      identity->clock_id = gst_clock_new_single_shot_id (clock, timestamp);
      GST_OBJECT_UNLOCK (identity);

      cret = gst_clock_id_wait (identity->clock_id, NULL);

      GST_OBJECT_LOCK (identity);
      if (identity->clock_id) {
        gst_clock_id_unref (identity->clock_id);
        identity->clock_id = NULL;
      }
      if (cret == GST_CLOCK_UNSCHEDULED)
        ret = GST_FLOW_UNEXPECTED;
    }
    GST_OBJECT_UNLOCK (identity);
  }

  identity->offset += GST_BUFFER_SIZE (buf);

  if (identity->sleep_time && ret == GST_FLOW_OK)
    g_usleep (identity->sleep_time);

  if (identity->single_segment && (trans->segment.format == GST_FORMAT_TIME)
      && (ret == GST_FLOW_OK)) {
    GST_BUFFER_TIMESTAMP (buf) = runtimestamp;
    GST_BUFFER_OFFSET (buf) = GST_CLOCK_TIME_NONE;
    GST_BUFFER_OFFSET_END (buf) = GST_CLOCK_TIME_NONE;
  }

  return ret;
}
예제 #9
0
static GstFlowReturn
gst_gdp_depay_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
{
  GstGDPDepay *this;
  GstFlowReturn ret = GST_FLOW_OK;
  GstCaps *caps;
  GstBuffer *buf;
  GstEvent *event;
  guint available;

  this = GST_GDP_DEPAY (parent);

  /* On DISCONT, get rid of accumulated data. We assume a buffer after the
   * DISCONT contains (part of) a new valid header, if not we error because we
   * lost sync */
  if (GST_BUFFER_IS_DISCONT (buffer)) {
    gst_adapter_clear (this->adapter);
    this->state = GST_GDP_DEPAY_STATE_HEADER;
  }
  gst_adapter_push (this->adapter, buffer);

  while (TRUE) {
    switch (this->state) {
      case GST_GDP_DEPAY_STATE_HEADER:
      {
        guint8 *header;

        /* collect a complete header, validate and store the header. Figure out
         * the payload length and switch to the PAYLOAD state */
        available = gst_adapter_available (this->adapter);
        if (available < GST_DP_HEADER_LENGTH)
          goto done;

        GST_LOG_OBJECT (this, "reading GDP header from adapter");
        header = gst_adapter_take (this->adapter, GST_DP_HEADER_LENGTH);
        if (!gst_dp_validate_header (GST_DP_HEADER_LENGTH, header)) {
          g_free (header);
          goto header_validate_error;
        }

        /* store types and payload length. Also store the header, which we need
         * to make the payload. */
        this->payload_length = gst_dp_header_payload_length (header);
        this->payload_type = gst_dp_header_payload_type (header);
        /* free previous header and store new one. */
        g_free (this->header);
        this->header = header;

        GST_LOG_OBJECT (this,
            "read GDP header, payload size %d, payload type %d, switching to state PAYLOAD",
            this->payload_length, this->payload_type);
        this->state = GST_GDP_DEPAY_STATE_PAYLOAD;
        break;
      }
      case GST_GDP_DEPAY_STATE_PAYLOAD:
      {
        /* in this state we wait for all the payload data to be available in the
         * adapter. Then we switch to the state where we actually process the
         * payload. */
        available = gst_adapter_available (this->adapter);
        if (available < this->payload_length)
          goto done;

        /* change state based on type */
        if (this->payload_type == GST_DP_PAYLOAD_BUFFER) {
          GST_LOG_OBJECT (this, "switching to state BUFFER");
          this->state = GST_GDP_DEPAY_STATE_BUFFER;
        } else if (this->payload_type == GST_DP_PAYLOAD_CAPS) {
          GST_LOG_OBJECT (this, "switching to state CAPS");
          this->state = GST_GDP_DEPAY_STATE_CAPS;
        } else if (this->payload_type >= GST_DP_PAYLOAD_EVENT_NONE) {
          GST_LOG_OBJECT (this, "switching to state EVENT");
          this->state = GST_GDP_DEPAY_STATE_EVENT;
        } else {
          goto wrong_type;
        }

        if (this->payload_length) {
          const guint8 *data;
          gboolean res;

          data = gst_adapter_map (this->adapter, this->payload_length);
          res = gst_dp_validate_payload (GST_DP_HEADER_LENGTH, this->header,
              data);
          gst_adapter_unmap (this->adapter);

          if (!res)
            goto payload_validate_error;
        }

        break;
      }
      case GST_GDP_DEPAY_STATE_BUFFER:
      {
        /* if we receive a buffer without caps first, we error out */
        if (!this->caps)
          goto no_caps;

        GST_LOG_OBJECT (this, "reading GDP buffer from adapter");
        buf = gst_dp_buffer_from_header (GST_DP_HEADER_LENGTH, this->header);
        if (!buf)
          goto buffer_failed;

        /* now take the payload if there is any */
        if (this->payload_length > 0) {
          GstMapInfo map;

          gst_buffer_map (buf, &map, GST_MAP_WRITE);
          gst_adapter_copy (this->adapter, map.data, 0, this->payload_length);
          gst_buffer_unmap (buf, &map);

          gst_adapter_flush (this->adapter, this->payload_length);
        }

        /* set caps and push */
        GST_LOG_OBJECT (this, "deserialized buffer %p, pushing, timestamp %"
            GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT
            ", offset %" G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT
            ", size %" G_GSIZE_FORMAT ", flags 0x%x",
            buf,
            GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
            GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
            GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf),
            gst_buffer_get_size (buf), GST_BUFFER_FLAGS (buf));
        ret = gst_pad_push (this->srcpad, buf);
        if (ret != GST_FLOW_OK)
          goto push_error;

        GST_LOG_OBJECT (this, "switching to state HEADER");
        this->state = GST_GDP_DEPAY_STATE_HEADER;
        break;
      }
      case GST_GDP_DEPAY_STATE_CAPS:
      {
        guint8 *payload;

        /* take the payload of the caps */
        GST_LOG_OBJECT (this, "reading GDP caps from adapter");
        payload = gst_adapter_take (this->adapter, this->payload_length);
        caps = gst_dp_caps_from_packet (GST_DP_HEADER_LENGTH, this->header,
            payload);
        g_free (payload);
        if (!caps)
          goto caps_failed;

        GST_DEBUG_OBJECT (this, "deserialized caps %" GST_PTR_FORMAT, caps);
        gst_caps_replace (&(this->caps), caps);
        gst_pad_set_caps (this->srcpad, caps);
        /* drop the creation ref we still have */
        gst_caps_unref (caps);

        GST_LOG_OBJECT (this, "switching to state HEADER");
        this->state = GST_GDP_DEPAY_STATE_HEADER;
        break;
      }
      case GST_GDP_DEPAY_STATE_EVENT:
      {
        guint8 *payload;

        GST_LOG_OBJECT (this, "reading GDP event from adapter");

        /* adapter doesn't like 0 length payload */
        if (this->payload_length > 0)
          payload = gst_adapter_take (this->adapter, this->payload_length);
        else
          payload = NULL;
        event = gst_dp_event_from_packet (GST_DP_HEADER_LENGTH, this->header,
            payload);
        g_free (payload);
        if (!event)
          goto event_failed;

        GST_DEBUG_OBJECT (this, "deserialized event %p of type %s, pushing",
            event, gst_event_type_get_name (event->type));
        gst_pad_push_event (this->srcpad, event);

        GST_LOG_OBJECT (this, "switching to state HEADER");
        this->state = GST_GDP_DEPAY_STATE_HEADER;
        break;
      }
    }
  }

done:
  return ret;

  /* ERRORS */
header_validate_error:
  {
    GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL),
        ("GDP packet header does not validate"));
    ret = GST_FLOW_ERROR;
    goto done;
  }
payload_validate_error:
  {
    GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL),
        ("GDP packet payload does not validate"));
    ret = GST_FLOW_ERROR;
    goto done;
  }
wrong_type:
  {
    GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL),
        ("GDP packet header is of wrong type"));
    ret = GST_FLOW_ERROR;
    goto done;
  }
no_caps:
  {
    GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL),
        ("Received a buffer without first receiving caps"));
    ret = GST_FLOW_NOT_NEGOTIATED;
    goto done;
  }
buffer_failed:
  {
    GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL),
        ("could not create buffer from GDP packet"));
    ret = GST_FLOW_ERROR;
    goto done;
  }
push_error:
  {
    GST_WARNING_OBJECT (this, "pushing depayloaded buffer returned %d", ret);
    goto done;
  }
caps_failed:
  {
    GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL),
        ("could not create caps from GDP packet"));
    ret = GST_FLOW_ERROR;
    goto done;
  }
event_failed:
  {
    GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL),
        ("could not create event from GDP packet"));
    ret = GST_FLOW_ERROR;
    goto done;
  }
}
예제 #10
0
/**
 * gst_buffer_create_sub:
 * @parent: a #GstBuffer.
 * @offset: the offset into parent #GstBuffer at which the new sub-buffer 
 *          begins.
 * @size: the size of the new #GstBuffer sub-buffer, in bytes.
 *
 * Creates a sub-buffer from @parent at @offset and @size.
 * This sub-buffer uses the actual memory space of the parent buffer.
 * This function will copy the offset and timestamp fields when the
 * offset is 0. If not, they will be set to #GST_CLOCK_TIME_NONE and 
 * #GST_BUFFER_OFFSET_NONE.
 * If @offset equals 0 and @size equals the total size of @buffer, the
 * duration and offset end fields are also copied. If not they will be set
 * to #GST_CLOCK_TIME_NONE and #GST_BUFFER_OFFSET_NONE.
 *
 * MT safe.
 * Returns: the new #GstBuffer.
 * Returns NULL if the arguments were invalid.
 */
GstBuffer *
gst_buffer_create_sub (GstBuffer * buffer, guint offset, guint size)
{
  GstSubBuffer *subbuffer;
  GstBuffer *parent;
  gboolean complete;

  g_return_val_if_fail (buffer != NULL, NULL);
  g_return_val_if_fail (buffer->mini_object.refcount > 0, NULL);
  g_return_val_if_fail (buffer->size >= offset + size, NULL);

  /* find real parent */
  if (GST_IS_SUBBUFFER (buffer)) {
    parent = GST_SUBBUFFER_CAST (buffer)->parent;
  } else {
    parent = buffer;
  }
  gst_buffer_ref (parent);

  /* create the new buffer */
  subbuffer = (GstSubBuffer *) gst_mini_object_new (_gst_subbuffer_type);
  subbuffer->parent = parent;

  GST_CAT_LOG (GST_CAT_BUFFER, "new subbuffer %p (parent %p)", subbuffer,
      parent);

  /* set the right values in the child */
  GST_BUFFER_DATA (GST_BUFFER_CAST (subbuffer)) = buffer->data + offset;
  GST_BUFFER_SIZE (GST_BUFFER_CAST (subbuffer)) = size;

  if ((offset == 0) && (size == GST_BUFFER_SIZE (buffer))) {
    /* copy all the flags except IN_CAPS */
    GST_BUFFER_FLAG_SET (subbuffer, GST_BUFFER_FLAGS (buffer));
    GST_BUFFER_FLAG_UNSET (subbuffer, GST_BUFFER_FLAG_IN_CAPS);
  } else {
    /* copy only PREROLL & GAP flags */
    GST_BUFFER_FLAG_SET (subbuffer, (GST_BUFFER_FLAGS (buffer) &
            (GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_GAP)));
  }

  /* we can copy the timestamp and offset if the new buffer starts at
   * offset 0 */
  if (offset == 0) {
    GST_BUFFER_TIMESTAMP (subbuffer) = GST_BUFFER_TIMESTAMP (buffer);
    GST_BUFFER_OFFSET (subbuffer) = GST_BUFFER_OFFSET (buffer);
    complete = (buffer->size == size);
  } else {
    GST_BUFFER_TIMESTAMP (subbuffer) = GST_CLOCK_TIME_NONE;
    GST_BUFFER_OFFSET (subbuffer) = GST_BUFFER_OFFSET_NONE;
    complete = FALSE;
  }

  if (complete) {
    GstCaps *caps;

    /* if we copied the complete buffer we can copy the duration,
     * offset_end and caps as well */
    GST_BUFFER_DURATION (subbuffer) = GST_BUFFER_DURATION (buffer);
    GST_BUFFER_OFFSET_END (subbuffer) = GST_BUFFER_OFFSET_END (buffer);
    if ((caps = GST_BUFFER_CAPS (buffer)))
      gst_caps_ref (caps);
    GST_BUFFER_CAPS (subbuffer) = caps;
  } else {
    GST_BUFFER_DURATION (subbuffer) = GST_CLOCK_TIME_NONE;
    GST_BUFFER_OFFSET_END (subbuffer) = GST_BUFFER_OFFSET_NONE;
    GST_BUFFER_CAPS (subbuffer) = NULL;
  }
  return GST_BUFFER_CAST (subbuffer);
}
예제 #11
0
gboolean gst_imx_blitter_set_input_frame(GstImxBlitter *blitter, GstBuffer *frame)
{
	gboolean ret;
	GstImxPhysMemMeta *phys_mem_meta;
	GstImxBlitterClass *klass;

	g_assert(blitter != NULL);
	klass = GST_IMX_BLITTER_CLASS(G_OBJECT_GET_CLASS(blitter));
	g_assert(klass->set_input_frame != NULL);

	if (frame == NULL)
		return klass->set_input_frame(blitter, NULL);

	phys_mem_meta = GST_IMX_PHYS_MEM_META_GET(frame);

	if ((phys_mem_meta == NULL) || (phys_mem_meta->phys_addr == 0))
	{
		GstFlowReturn flow_ret;
		GstBuffer *internal_input_frame;

		/* No DMA memory present; the input frame needs to be copied to an internal input frame */

		GST_TRACE_OBJECT(blitter, "input frame does not use DMA memory - copying input frame to internal frame");

		{
			if (blitter->dma_bufferpool == NULL)
			{
				GST_TRACE_OBJECT(blitter, "need to create internal bufferpool");

				/* DMA bufferpool does not exist yet - create it now,
				 * so that it can in turn create the internal input frame */

				GstCaps *caps = gst_video_info_to_caps(&(blitter->input_video_info));

				blitter->dma_bufferpool = gst_imx_blitter_create_bufferpool(
					blitter,
					caps,
					blitter->input_video_info.size,
					0, 0,
					NULL,
					NULL
				);

				gst_caps_unref(caps);

				if (blitter->dma_bufferpool == NULL)
				{
					GST_ERROR_OBJECT(blitter, "failed to create internal bufferpool");
					return FALSE;
				}
			}

			/* Future versions of this code may propose the internal bufferpool upstream;
			 * hence the is_active check */
			if (!gst_buffer_pool_is_active(blitter->dma_bufferpool))
				gst_buffer_pool_set_active(blitter->dma_bufferpool, TRUE);
		}

		/* Create new internal input frame */
		GST_TRACE_OBJECT(blitter, "acquiring buffer for internal input frame");
		internal_input_frame = NULL;
		flow_ret = gst_buffer_pool_acquire_buffer(blitter->dma_bufferpool, &internal_input_frame, NULL);
		if (flow_ret != GST_FLOW_OK)
		{
			if (internal_input_frame != NULL)
				gst_buffer_unref(internal_input_frame);

			GST_ERROR_OBJECT(blitter, "error acquiring input frame buffer: %s", gst_pad_mode_get_name(flow_ret));
			return FALSE;
		}

		/* Copy the input buffer's pixels to the internal input frame */
		{
			GstVideoFrame input_vidframe, internal_input_vidframe;

			gst_video_frame_map(&input_vidframe, &(blitter->input_video_info), frame, GST_MAP_READ);
			gst_video_frame_map(&internal_input_vidframe, &(blitter->input_video_info), internal_input_frame, GST_MAP_WRITE);

			/* gst_video_frame_copy() makes sure stride and plane offset values from both frames are respected */
			gst_video_frame_copy(&internal_input_vidframe, &input_vidframe);

			/* copy interlace flags */
			GST_BUFFER_FLAGS(internal_input_frame) |= (GST_BUFFER_FLAGS(frame) & (GST_VIDEO_BUFFER_FLAG_INTERLACED | GST_VIDEO_BUFFER_FLAG_TFF | GST_VIDEO_BUFFER_FLAG_RFF | GST_VIDEO_BUFFER_FLAG_ONEFIELD));

			gst_video_frame_unmap(&internal_input_vidframe);
			gst_video_frame_unmap(&input_vidframe);
		}

		ret = klass->set_input_frame(blitter, internal_input_frame);

		gst_buffer_unref(internal_input_frame);
	}
	else
	{
		GST_TRACE_OBJECT(blitter, "input frame uses DMA memory - setting it directly as input frame");
		ret = klass->set_input_frame(blitter, frame);
	}

	return ret;
}
예제 #12
0
static GstFlowReturn
gst_mpeg2dec_crop_buffer (GstMpeg2dec * dec, GstVideoCodecFrame * in_frame,
    GstVideoFrame * input_vframe)
{
  GstVideoCodecState *state;
  GstVideoInfo *info;
  GstVideoInfo *dinfo;
  guint c, n_planes;
  GstVideoFrame output_frame;
  GstFlowReturn ret;

  state = gst_video_decoder_get_output_state (GST_VIDEO_DECODER (dec));
  info = &state->info;
  dinfo = &dec->decoded_info;

  GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, dec,
      "Copying input buffer %ux%u (%" G_GSIZE_FORMAT ") to output buffer "
      "%ux%u (%" G_GSIZE_FORMAT ")", dinfo->width, dinfo->height,
      dinfo->size, info->width, info->height, info->size);

  ret =
      gst_video_decoder_allocate_output_frame (GST_VIDEO_DECODER (dec),
      in_frame);
  if (ret != GST_FLOW_OK)
    goto beach;

  if (!gst_video_frame_map (&output_frame, info, in_frame->output_buffer,
          GST_MAP_WRITE))
    goto map_fail;

  n_planes = GST_VIDEO_FRAME_N_PLANES (&output_frame);
  for (c = 0; c < n_planes; c++) {
    guint w, h, j;
    guint8 *sp, *dp;
    gint ss, ds;

    sp = GST_VIDEO_FRAME_PLANE_DATA (input_vframe, c);
    dp = GST_VIDEO_FRAME_PLANE_DATA (&output_frame, c);

    ss = GST_VIDEO_FRAME_PLANE_STRIDE (input_vframe, c);
    ds = GST_VIDEO_FRAME_PLANE_STRIDE (&output_frame, c);

    w = MIN (ABS (ss), ABS (ds));
    h = GST_VIDEO_FRAME_COMP_HEIGHT (&output_frame, c);

    GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy plane %u, w:%u h:%u ", c, w, h);

    for (j = 0; j < h; j++) {
      memcpy (dp, sp, w);
      dp += ds;
      sp += ss;
    }
  }

  gst_video_frame_unmap (&output_frame);

  GST_BUFFER_FLAGS (in_frame->output_buffer) =
      GST_BUFFER_FLAGS (input_vframe->buffer);

beach:
  gst_video_codec_state_unref (state);

  return ret;

map_fail:
  {
    GST_ERROR_OBJECT (dec, "Failed to map output frame");
    gst_video_codec_state_unref (state);
    return GST_FLOW_ERROR;
  }
}
예제 #13
0
static GstFlowReturn
gst_interlace_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
{
  GstInterlace *interlace = GST_INTERLACE (parent);
  GstFlowReturn ret = GST_FLOW_OK;
  gint num_fields = 0;
  int current_fields;
  const PulldownFormat *format;

  GST_DEBUG ("Received buffer at %u:%02u:%02u:%09u",
      (guint) (GST_BUFFER_TIMESTAMP (buffer) / (GST_SECOND * 60 * 60)),
      (guint) ((GST_BUFFER_TIMESTAMP (buffer) / (GST_SECOND * 60)) % 60),
      (guint) ((GST_BUFFER_TIMESTAMP (buffer) / GST_SECOND) % 60),
      (guint) (GST_BUFFER_TIMESTAMP (buffer) % GST_SECOND));

  GST_DEBUG ("duration %" GST_TIME_FORMAT " flags %04x %s %s %s",
      GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)),
      GST_BUFFER_FLAGS (buffer),
      (GST_BUFFER_FLAGS (buffer) & GST_VIDEO_BUFFER_FLAG_TFF) ? "tff" : "",
      (GST_BUFFER_FLAGS (buffer) & GST_VIDEO_BUFFER_FLAG_RFF) ? "rff" : "",
      (GST_BUFFER_FLAGS (buffer) & GST_VIDEO_BUFFER_FLAG_ONEFIELD) ? "onefield"
      : "");

  if (GST_BUFFER_FLAGS (buffer) & GST_BUFFER_FLAG_DISCONT) {
    GST_DEBUG ("discont");

    if (interlace->stored_frame) {
      gst_buffer_unref (interlace->stored_frame);
    }
    interlace->stored_frame = NULL;
    interlace->stored_fields = 0;

    if (interlace->top_field_first) {
      interlace->field_index = 0;
    } else {
      interlace->field_index = 1;
    }
  }

  if (interlace->timebase == GST_CLOCK_TIME_NONE) {
    /* get the initial ts */
    interlace->timebase = GST_BUFFER_TIMESTAMP (buffer);
  }

  format = &formats[interlace->pattern];

  if (interlace->stored_fields == 0
      && interlace->phase_index == interlace->pattern_offset
      && GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) {
    interlace->timebase = GST_BUFFER_TIMESTAMP (buffer);
    interlace->fields_since_timebase = 0;
  }

  if (!format->n_fields[interlace->phase_index]) {
    interlace->phase_index = 0;
  }

  current_fields = format->n_fields[interlace->phase_index];
  /* increment the phase index */
  interlace->phase_index++;
  GST_DEBUG ("incoming buffer assigned %d fields", current_fields);

  num_fields = interlace->stored_fields + current_fields;
  while (num_fields >= 2) {
    GstBuffer *output_buffer;
    int n_output_fields;
    gboolean interlaced = FALSE;

    GST_DEBUG ("have %d fields, %d current, %d stored",
        num_fields, current_fields, interlace->stored_fields);

    if (interlace->stored_fields > 0) {
      GST_DEBUG ("1 field from stored, 1 from current");

      output_buffer = gst_buffer_new_and_alloc (gst_buffer_get_size (buffer));
      /* take the first field from the stored frame */
      copy_field (interlace, output_buffer, interlace->stored_frame,
          interlace->field_index);
      interlace->stored_fields--;
      /* take the second field from the incoming buffer */
      copy_field (interlace, output_buffer, buffer, interlace->field_index ^ 1);
      current_fields--;
      n_output_fields = 2;
      interlaced = TRUE;
    } else {
      output_buffer = gst_buffer_make_writable (gst_buffer_ref (buffer));
      if (num_fields >= 3 && interlace->allow_rff) {
        GST_DEBUG ("3 fields from current");
        /* take both fields from incoming buffer */
        current_fields -= 3;
        n_output_fields = 3;
      } else {
        GST_DEBUG ("2 fields from current");
        /* take both buffers from incoming buffer */
        current_fields -= 2;
        n_output_fields = 2;
      }
    }
    num_fields -= n_output_fields;

    gst_interlace_decorate_buffer (interlace, output_buffer, n_output_fields,
        interlaced);
    interlace->fields_since_timebase += n_output_fields;
    interlace->field_index ^= (n_output_fields & 1);

    GST_DEBUG_OBJECT (interlace, "output timestamp %" GST_TIME_FORMAT
        " duration %" GST_TIME_FORMAT " flags %04x %s %s %s",
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (output_buffer)),
        GST_TIME_ARGS (GST_BUFFER_DURATION (output_buffer)),
        GST_BUFFER_FLAGS (output_buffer),
        (GST_BUFFER_FLAGS (output_buffer) & GST_VIDEO_BUFFER_FLAG_TFF) ? "tff" :
        "",
        (GST_BUFFER_FLAGS (output_buffer) & GST_VIDEO_BUFFER_FLAG_RFF) ? "rff" :
        "",
        (GST_BUFFER_FLAGS (output_buffer) & GST_VIDEO_BUFFER_FLAG_ONEFIELD) ?
        "onefield" : "");

    ret = gst_pad_push (interlace->srcpad, output_buffer);
    if (ret != GST_FLOW_OK) {
      GST_DEBUG_OBJECT (interlace, "Failed to push buffer %p", output_buffer);
      break;
    }
  }

  GST_DEBUG ("done.  %d fields remaining", current_fields);

  if (interlace->stored_frame) {
    gst_buffer_unref (interlace->stored_frame);
    interlace->stored_frame = NULL;
    interlace->stored_fields = 0;
  }

  if (current_fields > 0) {
    interlace->stored_frame = buffer;
    interlace->stored_fields = current_fields;
  } else {
    gst_buffer_unref (buffer);
  }
  return ret;
}
예제 #14
0
static GstFlowReturn
mpegtsmux_collected (GstCollectPads2 * pads, MpegTsMux * mux)
{
  GstFlowReturn ret = GST_FLOW_OK;
  MpegTsPadData *best = NULL;

  GST_DEBUG_OBJECT (mux, "Pads collected");

  if (G_UNLIKELY (mux->first)) {
    ret = mpegtsmux_create_streams (mux);
    if (G_UNLIKELY (ret != GST_FLOW_OK))
      return ret;

    mpegtsdemux_prepare_srcpad (mux);

    mux->first = FALSE;
  }

  best = mpegtsmux_choose_best_stream (mux);

  if (best != NULL) {
    TsMuxProgram *prog = best->prog;
    GstBuffer *buf = best->queued_buf;
    gint64 pts = -1;
    gboolean delta = TRUE;

    if (prog == NULL) {
      GST_ELEMENT_ERROR (mux, STREAM, MUX,
          ("Stream on pad %" GST_PTR_FORMAT
              " is not associated with any program", COLLECT_DATA_PAD (best)),
          (NULL));
      return GST_FLOW_ERROR;
    }

    if (mux->force_key_unit_event != NULL && best->stream->is_video_stream) {
      GstEvent *event;

      event = check_pending_key_unit_event (mux->force_key_unit_event,
          &best->collect.segment, GST_BUFFER_TIMESTAMP (buf),
          GST_BUFFER_FLAGS (buf), mux->pending_key_unit_ts);
      if (event) {
        GstClockTime running_time;
        guint count;
        GList *cur;

        mux->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
        gst_event_replace (&mux->force_key_unit_event, NULL);

        gst_video_event_parse_downstream_force_key_unit (event,
            NULL, NULL, &running_time, NULL, &count);

        GST_INFO_OBJECT (mux, "pushing downstream force-key-unit event %d "
            "%" GST_TIME_FORMAT " count %d", gst_event_get_seqnum (event),
            GST_TIME_ARGS (running_time), count);
        gst_pad_push_event (mux->srcpad, event);

        /* output PAT */
        mux->tsmux->last_pat_ts = -1;

        /* output PMT for each program */
        for (cur = g_list_first (mux->tsmux->programs); cur != NULL;
            cur = g_list_next (cur)) {
          TsMuxProgram *program = (TsMuxProgram *) cur->data;

          program->last_pmt_ts = -1;
        }
        tsmux_program_set_pcr_stream (prog, NULL);
      }
    }

    if (G_UNLIKELY (prog->pcr_stream == NULL)) {
      /* Take the first data stream for the PCR */
      GST_DEBUG_OBJECT (COLLECT_DATA_PAD (best),
          "Use stream (pid=%d) from pad as PCR for program (prog_id = %d)",
          MPEG_TS_PAD_DATA (best)->pid, MPEG_TS_PAD_DATA (best)->prog_id);

      /* Set the chosen PCR stream */
      tsmux_program_set_pcr_stream (prog, best->stream);
    }

    g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
    if (best->stream->is_video_stream)
      delta = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
    GST_DEBUG_OBJECT (mux, "delta: %d", delta);

    GST_DEBUG_OBJECT (COLLECT_DATA_PAD (best),
        "Chose stream for output (PID: 0x%04x)", best->pid);

    if (GST_CLOCK_TIME_IS_VALID (best->cur_ts)) {
      pts = GSTTIME_TO_MPEGTIME (best->cur_ts);
      GST_DEBUG_OBJECT (mux, "Buffer has TS %" GST_TIME_FORMAT " pts %"
          G_GINT64_FORMAT, GST_TIME_ARGS (best->cur_ts), pts);
    }

    tsmux_stream_add_data (best->stream, GST_BUFFER_DATA (buf),
        GST_BUFFER_SIZE (buf), buf, pts, -1, !delta);
    best->queued_buf = NULL;

    mux->is_delta = delta;
    while (tsmux_stream_bytes_in_buffer (best->stream) > 0) {
      if (!tsmux_write_stream_packet (mux->tsmux, best->stream)) {
        /* Failed writing data for some reason. Set appropriate error */
        GST_DEBUG_OBJECT (mux, "Failed to write data packet");
        GST_ELEMENT_ERROR (mux, STREAM, MUX,
            ("Failed writing output data to stream %04x", best->stream->id),
            (NULL));
        goto write_fail;
      }
    }
    if (prog->pcr_stream == best->stream) {
      mux->last_ts = best->last_ts;
    }
  } else {
    /* FIXME: Drain all remaining streams */
    /* At EOS */
    gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
  }

  return ret;
write_fail:
  return mux->last_flow_ret;
}