Ejemplo n.º 1
0
static GstFlowReturn
gst_y4m_encode_handle_frame (GstVideoEncoder * encoder,
    GstVideoCodecFrame * frame)
{
  GstY4mEncode *filter = GST_Y4M_ENCODE (encoder);
  GstClockTime timestamp;

  /* check we got some decent info from caps */
  if (GST_VIDEO_INFO_FORMAT (&filter->info) == GST_VIDEO_FORMAT_UNKNOWN)
    goto not_negotiated;

  timestamp = GST_BUFFER_TIMESTAMP (frame->input_buffer);

  if (G_UNLIKELY (!filter->header)) {
    gboolean tff = FALSE;

    if (GST_VIDEO_INFO_IS_INTERLACED (&filter->info)) {
      tff =
          GST_BUFFER_FLAG_IS_SET (frame->input_buffer,
          GST_VIDEO_BUFFER_FLAG_TFF);
    }
    frame->output_buffer = gst_y4m_encode_get_stream_header (filter, tff);
    filter->header = TRUE;
    frame->output_buffer =
        gst_buffer_append (frame->output_buffer,
        gst_y4m_encode_get_frame_header (filter));
  } else {
    frame->output_buffer = gst_y4m_encode_get_frame_header (filter);
  }

  frame->output_buffer =
      gst_buffer_append (frame->output_buffer,
      gst_buffer_copy (frame->input_buffer));

  /* decorate */
  frame->output_buffer = gst_buffer_make_writable (frame->output_buffer);
  GST_BUFFER_TIMESTAMP (frame->output_buffer) = timestamp;

  return gst_video_encoder_finish_frame (encoder, frame);

not_negotiated:
  {
    GST_ELEMENT_ERROR (filter, CORE, NEGOTIATION, (NULL),
        ("format wasn't negotiated"));

    return GST_FLOW_NOT_NEGOTIATED;
  }
}
Ejemplo n.º 2
0
static void
dxr3videosink_chain (GstPad * pad, GstData * _data)
{
  GstBuffer *buf = GST_BUFFER (_data);
  Dxr3VideoSink *sink;

  g_return_if_fail (pad != NULL);
  g_return_if_fail (GST_IS_PAD (pad));
  g_return_if_fail (buf != NULL);

  sink = DXR3VIDEOSINK (gst_pad_get_parent (pad));

  if (GST_IS_EVENT (buf)) {
    dxr3videosink_handle_event (pad, GST_EVENT (buf));
    return;
  }

/*   fprintf (stderr, "^^^^^^ Video block\n"); */

  if (sink->cur_buf == NULL) {
    sink->cur_buf = buf;
  } else {
    sink->cur_buf = gst_buffer_append (sink->cur_buf, buf);
  }

  sink->last_ts = GST_BUFFER_TIMESTAMP (buf);

  dxr3videosink_parse_data (sink);
}
Ejemplo n.º 3
0
static gint
gst_ffmpegauddec_frame (GstFFMpegAudDec * ffmpegdec,
    guint8 * data, guint size, gint * got_data, GstFlowReturn * ret)
{
  GstFFMpegAudDecClass *oclass;
  GstBuffer *outbuf = NULL;
  gint have_data = 0, len = 0;

  if (G_UNLIKELY (ffmpegdec->context->codec == NULL))
    goto no_codec;

  GST_LOG_OBJECT (ffmpegdec, "data:%p, size:%d", data, size);

  *ret = GST_FLOW_OK;
  ffmpegdec->context->frame_number++;

  oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));

  len =
      gst_ffmpegauddec_audio_frame (ffmpegdec, oclass->in_plugin, data, size,
      &outbuf, ret);

  if (outbuf)
    have_data = 1;

  if (len < 0 || have_data < 0) {
    GST_WARNING_OBJECT (ffmpegdec,
        "avdec_%s: decoding error (len: %d, have_data: %d)",
        oclass->in_plugin->name, len, have_data);
    *got_data = 0;
    goto beach;
  } else if (len == 0 && have_data == 0) {
    *got_data = 0;
    goto beach;
  } else {
    /* this is where I lost my last clue on ffmpeg... */
    *got_data = 1;
  }

  if (outbuf) {
    GST_LOG_OBJECT (ffmpegdec, "Decoded data, now storing buffer %p", outbuf);

    if (ffmpegdec->outbuf)
      ffmpegdec->outbuf = gst_buffer_append (ffmpegdec->outbuf, outbuf);
    else
      ffmpegdec->outbuf = outbuf;
  } else {
    GST_DEBUG_OBJECT (ffmpegdec, "We didn't get a decoded buffer");
  }

beach:
  return len;

  /* ERRORS */
no_codec:
  {
    GST_ERROR_OBJECT (ffmpegdec, "no codec context");
    return -1;
  }
}
Ejemplo n.º 4
0
static GstFlowReturn
gst_rtp_opus_pay_handle_buffer (GstRTPBasePayload * basepayload,
    GstBuffer * buffer)
{
  GstBuffer *outbuf;
  GstClockTime pts, dts, duration;
  CopyMetaData data;

  pts = GST_BUFFER_PTS (buffer);
  dts = GST_BUFFER_DTS (buffer);
  duration = GST_BUFFER_DURATION (buffer);

  outbuf = gst_rtp_buffer_new_allocate (0, 0, 0);
  data.pay = GST_RTP_OPUS_PAY (basepayload);
  data.outbuf = outbuf;
  gst_buffer_foreach_meta (buffer, foreach_metadata, &data);
  outbuf = gst_buffer_append (outbuf, buffer);

  GST_BUFFER_PTS (outbuf) = pts;
  GST_BUFFER_DTS (outbuf) = dts;
  GST_BUFFER_DURATION (outbuf) = duration;

  /* Push out */
  return gst_rtp_base_payload_push (basepayload, outbuf);
}
Ejemplo n.º 5
0
/* Handles decrypted buffers only */
static GstFlowReturn
gst_hls_demux_handle_buffer (GstAdaptiveDemux * demux,
    GstAdaptiveDemuxStream * stream, GstBuffer * buffer, gboolean force)
{
  GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);

  if (G_UNLIKELY (hlsdemux->do_typefind && buffer != NULL)) {
    GstCaps *caps = NULL;
    GstMapInfo info;
    guint buffer_size;
    GstTypeFindProbability prob = GST_TYPE_FIND_NONE;

    if (hlsdemux->pending_typefind_buffer)
      buffer = gst_buffer_append (hlsdemux->pending_typefind_buffer, buffer);
    hlsdemux->pending_typefind_buffer = NULL;

    gst_buffer_map (buffer, &info, GST_MAP_READ);
    buffer_size = info.size;

    /* Typefind could miss if buffer is too small. In this case we
     * will retry later */
    if (buffer_size >= (2 * 1024)) {
      caps =
          gst_type_find_helper_for_data (GST_OBJECT_CAST (hlsdemux), info.data,
          info.size, &prob);
    }
    gst_buffer_unmap (buffer, &info);

    if (G_UNLIKELY (!caps)) {
      /* Only fail typefinding if we already a good amount of data
       * and we still don't know the type */
      if (buffer_size > (2 * 1024 * 1024) || force) {
        GST_ELEMENT_ERROR (hlsdemux, STREAM, TYPE_NOT_FOUND,
            ("Could not determine type of stream"), (NULL));
        gst_buffer_unref (buffer);
        return GST_FLOW_NOT_NEGOTIATED;
      } else {
        hlsdemux->pending_typefind_buffer = buffer;
        return GST_FLOW_OK;
      }
    }

    GST_DEBUG_OBJECT (hlsdemux, "Typefind result: %" GST_PTR_FORMAT " prob:%d",
        caps, prob);

    gst_adaptive_demux_stream_set_caps (stream, caps);
    hlsdemux->do_typefind = FALSE;
  }

  g_assert (hlsdemux->pending_typefind_buffer == NULL);

  if (buffer) {
    buffer = gst_buffer_make_writable (buffer);
    GST_BUFFER_OFFSET (buffer) = hlsdemux->current_offset;
    hlsdemux->current_offset += gst_buffer_get_size (buffer);
    GST_BUFFER_OFFSET_END (buffer) = hlsdemux->current_offset;
    return gst_adaptive_demux_stream_push_buffer (stream, buffer);
  }
  return GST_FLOW_OK;
}
Ejemplo n.º 6
0
static void
gst_mikmod_loop (GstElement * element)
{
  GstMikMod *mikmod;
  GstBuffer *buffer_in;

  g_return_if_fail (element != NULL);
  g_return_if_fail (GST_IS_MIKMOD (element));

  mikmod = GST_MIKMOD (element);
  srcpad = mikmod->srcpad;
  mikmod->Buffer = NULL;

  if (!mikmod->initialized) {
    while ((buffer_in = GST_BUFFER (gst_pad_pull (mikmod->sinkpad)))) {
      if (GST_IS_EVENT (buffer_in)) {
        GstEvent *event = GST_EVENT (buffer_in);

        if (GST_EVENT_TYPE (event) == GST_EVENT_EOS)
          break;
      } else {
        if (mikmod->Buffer) {
          mikmod->Buffer = gst_buffer_append (mikmod->Buffer, buffer_in);
        } else {
          mikmod->Buffer = buffer_in;
        }
      }
    }

    if (!GST_PAD_CAPS (mikmod->srcpad)) {
      if (GST_PAD_LINK_SUCCESSFUL (gst_pad_renegotiate (mikmod->srcpad))) {
        GST_ELEMENT_ERROR (mikmod, CORE, NEGOTIATION, (NULL), (NULL));
        return;
      }
    }

    MikMod_RegisterDriver (&drv_gst);
    MikMod_RegisterAllLoaders ();

    MikMod_Init ("");
    reader = GST_READER_new (mikmod);
    module = Player_LoadGeneric (reader, 64, 0);

    gst_buffer_unref (mikmod->Buffer);

    if (!Player_Active ())
      Player_Start (module);

    mikmod->initialized = TRUE;
  }

  if (Player_Active ()) {
    timestamp = (module->sngtime / 1024.0) * GST_SECOND;
    drv_gst.Update ();
  } else {
    gst_element_set_eos (GST_ELEMENT (mikmod));
    gst_pad_push (mikmod->srcpad, GST_DATA (gst_event_new (GST_EVENT_EOS)));
  }
}
Ejemplo n.º 7
0
static GstFlowReturn
gst_y4m_encode_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
  GstY4mEncode *filter = GST_Y4M_ENCODE (parent);
  GstBuffer *outbuf;
  GstClockTime timestamp;

  /* check we got some decent info from caps */
  if (GST_VIDEO_INFO_FORMAT (&filter->info) == GST_VIDEO_FORMAT_UNKNOWN)
    goto not_negotiated;

  timestamp = GST_BUFFER_TIMESTAMP (buf);

  if (G_UNLIKELY (!filter->header)) {
    gboolean tff;

    if (GST_VIDEO_INFO_IS_INTERLACED (&filter->info)) {
      tff = GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_BUFFER_FLAG_TFF);
    }
    outbuf = gst_y4m_encode_get_stream_header (filter, tff);
    filter->header = TRUE;
    outbuf =
        gst_buffer_append (outbuf, gst_y4m_encode_get_frame_header (filter));
  } else {
    outbuf = gst_y4m_encode_get_frame_header (filter);
  }
  /* join with data, FIXME, strides are all wrong etc */
  outbuf = gst_buffer_append (outbuf, buf);
  /* decorate */
  outbuf = gst_buffer_make_writable (outbuf);

  GST_BUFFER_TIMESTAMP (outbuf) = timestamp;

  return gst_pad_push (filter->srcpad, outbuf);

  /* ERRORS */
not_negotiated:
  {
    GST_ELEMENT_ERROR (filter, CORE, NEGOTIATION, (NULL),
        ("format wasn't negotiated before chain function"));
    gst_buffer_unref (buf);
    return GST_FLOW_NOT_NEGOTIATED;
  }
}
static GstFlowReturn
gst_rtp_base_audio_payload_push_buffer (GstRTPBaseAudioPayload *
    baseaudiopayload, GstBuffer * buffer, GstClockTime timestamp)
{
  GstRTPBasePayload *basepayload;
  GstRTPBaseAudioPayloadPrivate *priv;
  GstBuffer *outbuf;
  guint payload_len;
  GstFlowReturn ret;

  priv = baseaudiopayload->priv;
  basepayload = GST_RTP_BASE_PAYLOAD (baseaudiopayload);

  payload_len = gst_buffer_get_size (buffer);

  GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT,
      payload_len, GST_TIME_ARGS (timestamp));

  /* create just the RTP header buffer */
  outbuf = gst_rtp_base_payload_allocate_output_buffer (basepayload, 0, 0, 0);

  /* set metadata */
  gst_rtp_base_audio_payload_set_meta (baseaudiopayload, outbuf, payload_len,
      timestamp);

  if (priv->buffer_list) {
    GstBufferList *list;
    guint i, len;

    list = gst_buffer_list_new ();
    len = gst_buffer_list_length (list);

    for (i = 0; i < len; i++) {
      /* FIXME */
      g_warning ("bufferlist not implemented");
      gst_buffer_list_add (list, outbuf);
      gst_buffer_list_add (list, buffer);
    }

    GST_DEBUG_OBJECT (baseaudiopayload, "Pushing list %p", list);
    ret = gst_rtp_base_payload_push_list (basepayload, list);
  } else {
    CopyMetaData data;

    /* copy payload */
    data.pay = baseaudiopayload;
    data.outbuf = outbuf;
    gst_buffer_foreach_meta (buffer, foreach_metadata, &data);
    outbuf = gst_buffer_append (outbuf, buffer);

    GST_DEBUG_OBJECT (baseaudiopayload, "Pushing buffer %p", outbuf);
    ret = gst_rtp_base_payload_push (basepayload, outbuf);
  }

  return ret;
}
static GstFlowReturn
gst_rtp_sbc_pay_flush_buffers (GstRtpSBCPay * sbcpay)
{
  GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
  guint available;
  guint max_payload;
  GstBuffer *outbuf, *paybuf;
  guint8 *payload_data;
  guint frame_count;
  guint payload_length;
  struct rtp_payload *payload;

  if (sbcpay->frame_length == 0) {
    GST_ERROR_OBJECT (sbcpay, "Frame length is 0");
    return GST_FLOW_ERROR;
  }

  available = gst_adapter_available (sbcpay->adapter);

  max_payload =
      gst_rtp_buffer_calc_payload_len (GST_RTP_BASE_PAYLOAD_MTU (sbcpay) -
      RTP_SBC_PAYLOAD_HEADER_SIZE, 0, 0);

  max_payload = MIN (max_payload, available);
  frame_count = max_payload / sbcpay->frame_length;
  payload_length = frame_count * sbcpay->frame_length;
  if (payload_length == 0)      /* Nothing to send */
    return GST_FLOW_OK;

  outbuf = gst_rtp_buffer_new_allocate (RTP_SBC_PAYLOAD_HEADER_SIZE, 0, 0);

  /* get payload */
  gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);

  gst_rtp_buffer_set_payload_type (&rtp, GST_RTP_BASE_PAYLOAD_PT (sbcpay));

  /* write header and copy data into payload */
  payload_data = gst_rtp_buffer_get_payload (&rtp);
  payload = (struct rtp_payload *) payload_data;
  memset (payload, 0, sizeof (struct rtp_payload));
  payload->frame_count = frame_count;

  gst_rtp_buffer_unmap (&rtp);

  paybuf = gst_adapter_take_buffer_fast (sbcpay->adapter, payload_length);
  gst_rtp_copy_meta (GST_ELEMENT_CAST (sbcpay), outbuf, paybuf,
      g_quark_from_static_string (GST_META_TAG_AUDIO_STR));
  outbuf = gst_buffer_append (outbuf, paybuf);

  /* FIXME: what about duration? */
  GST_BUFFER_PTS (outbuf) = sbcpay->timestamp;
  GST_DEBUG_OBJECT (sbcpay, "Pushing %d bytes", payload_length);

  return gst_rtp_base_payload_push (GST_RTP_BASE_PAYLOAD (sbcpay), outbuf);
}
Ejemplo n.º 10
0
static GstFlowReturn
_download_chain (GstBuffer * buffer, gpointer user_data)
{
  dl_context *ctx = user_data;

  if (ctx->buffer)
    gst_buffer_append (ctx->buffer, buffer);
  else
    ctx->buffer = buffer;

  return GST_FLOW_OK;
}
Ejemplo n.º 11
0
static GstFlowReturn
gst_rtp_opus_pay_handle_buffer (GstRTPBasePayload * basepayload,
    GstBuffer * buffer)
{
  GstBuffer *outbuf;

  outbuf = gst_rtp_buffer_new_allocate (0, 0, 0);
  outbuf = gst_buffer_append (outbuf, gst_buffer_ref (buffer));

  /* Push out */
  return gst_rtp_base_payload_push (basepayload, outbuf);
}
Ejemplo n.º 12
0
static GstFlowReturn
gst_hls_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
  GstHLSDemux *demux = GST_HLS_DEMUX (parent);

  if (demux->playlist == NULL)
    demux->playlist = buf;
  else
    demux->playlist = gst_buffer_append (demux->playlist, buf);

  return GST_FLOW_OK;
}
static GstBufferList *
create_buffer_list (guint * data_size)
{
  GstBufferList *list;
  GstBuffer *rtp_buffer;
  GstBuffer *data_buffer;

  list = gst_buffer_list_new ();

  /*** First group, i.e. first packet. **/

  /* Create the RTP header buffer */
  rtp_buffer = gst_buffer_new_allocate (NULL, RTP_HEADER_SIZE, NULL);
  gst_buffer_memset (rtp_buffer, 0, 0, RTP_HEADER_SIZE);

  /* Create the buffer that holds the payload */
  data_buffer = gst_buffer_new_allocate (NULL, RTP_PAYLOAD_SIZE, NULL);
  gst_buffer_memset (data_buffer, 0, 0, RTP_PAYLOAD_SIZE);

  /* Create a new group to hold the rtp header and the payload */
  gst_buffer_list_add (list, gst_buffer_append (rtp_buffer, data_buffer));

  /***  Second group, i.e. second packet. ***/

  /* Create the RTP header buffer */
  rtp_buffer = gst_buffer_new_allocate (NULL, RTP_HEADER_SIZE, NULL);
  gst_buffer_memset (rtp_buffer, 0, 0, RTP_HEADER_SIZE);

  /* Create the buffer that holds the payload */
  data_buffer = gst_buffer_new_allocate (NULL, RTP_PAYLOAD_SIZE, NULL);
  gst_buffer_memset (data_buffer, 0, 0, RTP_PAYLOAD_SIZE);

  /* Create a new group to hold the rtp header and the payload */
  gst_buffer_list_add (list, gst_buffer_append (rtp_buffer, data_buffer));

  /* Calculate the size of the data */
  *data_size = 2 * RTP_HEADER_SIZE + 2 * RTP_PAYLOAD_SIZE;

  return list;
}
Ejemplo n.º 14
0
static GstFlowReturn
gst_rtp_mp2t_pay_flush (GstRTPMP2TPay * rtpmp2tpay)
{
  guint avail, mtu;
  GstFlowReturn ret = GST_FLOW_OK;
  GstBuffer *outbuf;

  avail = gst_adapter_available (rtpmp2tpay->adapter);

  mtu = GST_RTP_BASE_PAYLOAD_MTU (rtpmp2tpay);

  while (avail > 0 && (ret == GST_FLOW_OK)) {
    guint towrite;
    guint payload_len;
    guint packet_len;
    GstBuffer *paybuf;

    /* this will be the total length of the packet */
    packet_len = gst_rtp_buffer_calc_packet_len (avail, 0, 0);

    /* fill one MTU or all available bytes */
    towrite = MIN (packet_len, mtu);

    /* this is the payload length */
    payload_len = gst_rtp_buffer_calc_payload_len (towrite, 0, 0);
    payload_len -= payload_len % 188;

    /* need whole packets */
    if (!payload_len)
      break;

    /* create buffer to hold the payload */
    outbuf = gst_rtp_buffer_new_allocate (0, 0, 0);

    /* get payload */
    paybuf = gst_adapter_take_buffer_fast (rtpmp2tpay->adapter, payload_len);
    gst_rtp_copy_meta (GST_ELEMENT_CAST (rtpmp2tpay), outbuf, paybuf, 0);
    outbuf = gst_buffer_append (outbuf, paybuf);
    avail -= payload_len;

    GST_BUFFER_PTS (outbuf) = rtpmp2tpay->first_ts;
    GST_BUFFER_DURATION (outbuf) = rtpmp2tpay->duration;

    GST_DEBUG_OBJECT (rtpmp2tpay, "pushing buffer of size %u",
        (guint) gst_buffer_get_size (outbuf));

    ret = gst_rtp_base_payload_push (GST_RTP_BASE_PAYLOAD (rtpmp2tpay), outbuf);
  }

  return ret;
}
Ejemplo n.º 15
0
static GstFlowReturn
gst_rtp_gsm_pay_handle_buffer (GstRTPBasePayload * basepayload,
    GstBuffer * buffer)
{
  GstRTPGSMPay *rtpgsmpay;
  guint payload_len;
  GstBuffer *outbuf;
  GstClockTime timestamp, duration;
  GstFlowReturn ret;

  rtpgsmpay = GST_RTP_GSM_PAY (basepayload);

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

  /* FIXME, only one GSM frame per RTP packet for now */
  payload_len = gst_buffer_get_size (buffer);

  /* FIXME, just error out for now */
  if (payload_len > GST_RTP_BASE_PAYLOAD_MTU (rtpgsmpay))
    goto too_big;

  outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);

  /* copy timestamp and duration */
  GST_BUFFER_PTS (outbuf) = timestamp;
  GST_BUFFER_DURATION (outbuf) = duration;

  gst_rtp_copy_meta (GST_ELEMENT_CAST (rtpgsmpay), outbuf, buffer,
      g_quark_from_static_string (GST_META_TAG_AUDIO_STR));

  /* append payload */
  outbuf = gst_buffer_append (outbuf, buffer);

  GST_DEBUG ("gst_rtp_gsm_pay_chain: pushing buffer of size %" G_GSIZE_FORMAT,
      gst_buffer_get_size (outbuf));

  ret = gst_rtp_base_payload_push (basepayload, outbuf);

  return ret;

  /* ERRORS */
too_big:
  {
    GST_ELEMENT_ERROR (rtpgsmpay, STREAM, ENCODE, (NULL),
        ("payload_len %u > mtu %u", payload_len,
            GST_RTP_BASE_PAYLOAD_MTU (rtpgsmpay)));
    return GST_FLOW_ERROR;
  }
}
Ejemplo n.º 16
0
/* Internal method only. Tries to merge buffers at the head of the queue
 * to form a single larger buffer of size 'size'.
 *
 * Returns TRUE if it managed to merge anything.
 */
static gboolean
gst_adapter_try_to_merge_up (GstAdapter * adapter, gsize size)
{
  GstBuffer *cur, *head;
  GSList *g;
  gboolean ret = FALSE;
  gsize hsize;

  g = adapter->buflist;
  if (g == NULL)
    return FALSE;

  head = g->data;

  hsize = gst_buffer_get_size (head);

  /* Remove skipped part from the buffer (otherwise the buffer might grow indefinitely) */
  head = gst_buffer_make_writable (head);
  gst_buffer_resize (head, adapter->skip, hsize - adapter->skip);
  hsize -= adapter->skip;
  adapter->skip = 0;
  g->data = head;

  g = g_slist_next (g);

  while (g != NULL && hsize < size) {
    cur = g->data;
    /* Merge the head buffer and the next in line */
    GST_LOG_OBJECT (adapter, "Merging buffers of size %" G_GSIZE_FORMAT " & %"
        G_GSIZE_FORMAT " in search of target %" G_GSIZE_FORMAT,
        hsize, gst_buffer_get_size (cur), size);

    head = gst_buffer_append (head, cur);
    hsize = gst_buffer_get_size (head);
    ret = TRUE;

    /* Delete the front list item, and store our new buffer in the 2nd list
     * item */
    adapter->buflist = g_slist_delete_link (adapter->buflist, adapter->buflist);
    g->data = head;

    /* invalidate scan position */
    adapter->scan_offset = 0;
    adapter->scan_entry = NULL;

    g = g_slist_next (g);
  }

  return ret;
}
Ejemplo n.º 17
0
static GstFlowReturn gst_vqe_sdp_demux_sink_chain(
    GstPad *pad, GstObject *parent, GstBuffer *buffer)
{
  GstVQESDPDemux * demux = GST_VQE_SDP_DEMUX(parent);
  if (!demux->sdpfile_complete) {
    if (!demux->sdpfile)
      demux->sdpfile = gst_buffer_new();
    demux->sdpfile = gst_buffer_append(demux->sdpfile, buffer);
    return GST_FLOW_OK;
  }
  else {
    return GST_FLOW_EOS;
  }
}
Ejemplo n.º 18
0
static GstFlowReturn
gst_asf_parse_pull_headers (GstAsfParse * asfparse)
{
  GstBuffer *guid_and_size = NULL;
  GstBuffer *headers = NULL;
  guint64 size;
  GstFlowReturn ret;
  GstMapInfo map;

  if ((ret = gst_pad_pull_range (asfparse->sinkpad, asfparse->offset,
              ASF_GUID_OBJSIZE_SIZE, &guid_and_size)) != GST_FLOW_OK) {
    GST_ERROR_OBJECT (asfparse, "Failed to pull data from headers");
    goto leave;
  }
  asfparse->offset += ASF_GUID_OBJSIZE_SIZE;
  gst_buffer_map (guid_and_size, &map, GST_MAP_READ);
  size = gst_asf_match_and_peek_obj_size (map.data,
      &(guids[ASF_HEADER_OBJECT_INDEX]));
  gst_buffer_unmap (guid_and_size, &map);

  if (size == 0) {
    GST_ERROR_OBJECT (asfparse, "ASF starting identifier missing");
    goto leave;
  }

  if ((ret = gst_pad_pull_range (asfparse->sinkpad, asfparse->offset,
              size - ASF_GUID_OBJSIZE_SIZE, &headers)) != GST_FLOW_OK) {
    GST_ERROR_OBJECT (asfparse, "Failed to pull data from headers");
    goto leave;
  }
  headers = gst_buffer_append (guid_and_size, headers);
  guid_and_size = NULL;
  asfparse->offset += size - ASF_GUID_OBJSIZE_SIZE;
  if (!gst_asf_parse_headers (headers, asfparse->asfinfo)) {
    goto leave;
  }
  return gst_asf_parse_push (asfparse, headers);

leave:
  if (headers)
    gst_buffer_unref (headers);
  if (guid_and_size)
    gst_buffer_unref (guid_and_size);
  return ret;
}
Ejemplo n.º 19
0
static GstFlowReturn
gst_hls_demux_data_received (GstAdaptiveDemux * demux,
    GstAdaptiveDemuxStream * stream)
{
  GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
  gsize available;
  GstBuffer *buffer = NULL;

  available = gst_adapter_available (stream->adapter);

  /* Is it encrypted? */
  if (hlsdemux->current_key) {
    GError *err = NULL;
    GstBuffer *tmp_buffer;

    /* must be a multiple of 16 */
    available = available & (~0xF);

    if (available == 0) {
      return GST_FLOW_OK;
    }

    buffer = gst_adapter_take_buffer (stream->adapter, available);
    buffer = gst_hls_demux_decrypt_fragment (hlsdemux, buffer, &err);
    if (buffer == NULL) {
      GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Failed to decrypt buffer"),
          ("decryption failed %s", err->message));
      g_error_free (err);
      return GST_FLOW_ERROR;
    }

    tmp_buffer = hlsdemux->pending_buffer;
    hlsdemux->pending_buffer = buffer;
    buffer = tmp_buffer;
  } else {
    buffer = gst_adapter_take_buffer (stream->adapter, available);
    if (hlsdemux->pending_buffer) {
      buffer = gst_buffer_append (hlsdemux->pending_buffer, buffer);
      hlsdemux->pending_buffer = NULL;
    }
  }

  return gst_hls_demux_handle_buffer (demux, stream, buffer, FALSE);
}
Ejemplo n.º 20
0
gboolean
gst_fragment_add_buffer (GstFragment * fragment, GstBuffer * buffer)
{
  g_return_val_if_fail (fragment != NULL, FALSE);
  g_return_val_if_fail (buffer != NULL, FALSE);

  if (fragment->completed) {
    GST_WARNING ("Fragment is completed, could not add more buffers");
    return FALSE;
  }

  GST_DEBUG ("Adding new buffer to the fragment");
  /* We steal the buffers you pass in */
  if (fragment->priv->buffer == NULL)
    fragment->priv->buffer = buffer;
  else
    fragment->priv->buffer = gst_buffer_append (fragment->priv->buffer, buffer);
  return TRUE;
}
Ejemplo n.º 21
0
static GstFlowReturn
gst_nsfdec_chain (GstPad * pad, GstBuffer * buffer)
{
  GstNsfDec *nsfdec;

  nsfdec = GST_NSFDEC (gst_pad_get_parent (pad));

  /* collect all data, we start doing something when we get an EOS
   * event */
  if (nsfdec->tune_buffer) {
    nsfdec->tune_buffer = gst_buffer_append (nsfdec->tune_buffer, buffer);
  } else {
    nsfdec->tune_buffer = buffer;
  }

  gst_object_unref (nsfdec);

  return GST_FLOW_OK;
}
Ejemplo n.º 22
0
static GstFlowReturn
gst_asf_parse_pull_indexes (GstAsfParse * asfparse)
{
  GstBuffer *guid_and_size;
  GstBuffer *buf;
  guint64 obj_size;
  GstFlowReturn ret = GST_FLOW_OK;
  while (1) {
    guid_and_size = NULL;
    ret = gst_pad_pull_range (asfparse->sinkpad, asfparse->offset,
        ASF_GUID_OBJSIZE_SIZE, &guid_and_size);
    if (ret != GST_FLOW_OK)
      break;
    /* we can peek at the object size */
    obj_size = gst_asf_match_and_peek_obj_size_buf (guid_and_size, NULL);
    if (obj_size == 0) {
      GST_ERROR_OBJECT (asfparse, "Incomplete object found");
      gst_buffer_unref (guid_and_size);
      ret = GST_FLOW_ERROR;
      break;
    }
    asfparse->offset += ASF_GUID_OBJSIZE_SIZE;

    /* pull the rest of the object */
    buf = NULL;
    ret = gst_pad_pull_range (asfparse->sinkpad, asfparse->offset, obj_size,
        &buf);
    if (ret != GST_FLOW_OK) {
      gst_buffer_unref (guid_and_size);
      break;
    }
    asfparse->offset += obj_size - ASF_GUID_OBJSIZE_SIZE;

    buf = gst_buffer_append (guid_and_size, buf);
    ret = gst_asf_parse_push (asfparse, buf);
    if (ret != GST_FLOW_OK)
      break;
  }
  return ret;
}
static GstFlowReturn
gst_rtp_g723_pay_flush (GstRTPG723Pay * pay)
{
  GstBuffer *outbuf, *payload_buf;
  GstFlowReturn ret;
  guint avail;
  GstRTPBuffer rtp = { NULL };

  avail = gst_adapter_available (pay->adapter);

  outbuf = gst_rtp_buffer_new_allocate (0, 0, 0);

  gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);

  GST_BUFFER_PTS (outbuf) = pay->timestamp;
  GST_BUFFER_DURATION (outbuf) = pay->duration;

  /* copy G723 data as payload */
  payload_buf = gst_adapter_take_buffer_fast (pay->adapter, avail);

  pay->timestamp = GST_CLOCK_TIME_NONE;
  pay->duration = 0;

  /* set discont and marker */
  if (pay->discont) {
    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
    gst_rtp_buffer_set_marker (&rtp, TRUE);
    pay->discont = FALSE;
  }
  gst_rtp_buffer_unmap (&rtp);
  gst_rtp_copy_meta (GST_ELEMENT_CAST (pay), outbuf, payload_buf,
      g_quark_from_static_string (GST_META_TAG_AUDIO_STR));

  outbuf = gst_buffer_append (outbuf, payload_buf);

  ret = gst_rtp_base_payload_push (GST_RTP_BASE_PAYLOAD (pay), outbuf);

  return ret;
}
Ejemplo n.º 24
0
/**
 * gst_rtp_base_audio_payload_flush:
 * @baseaudiopayload: a #GstRTPBasePayload
 * @payload_len: length of payload
 * @timestamp: a #GstClockTime
 *
 * Create an RTP buffer and store @payload_len bytes of the adapter as the
 * payload. Set the timestamp on the new buffer to @timestamp before pushing
 * the buffer downstream.
 *
 * If @payload_len is -1, all pending bytes will be flushed. If @timestamp is
 * -1, the timestamp will be calculated automatically.
 *
 * Returns: a #GstFlowReturn
 */
GstFlowReturn
gst_rtp_base_audio_payload_flush (GstRTPBaseAudioPayload * baseaudiopayload,
    guint payload_len, GstClockTime timestamp)
{
  GstRTPBasePayload *basepayload;
  GstRTPBaseAudioPayloadPrivate *priv;
  GstBuffer *outbuf;
  GstFlowReturn ret;
  GstAdapter *adapter;
  guint64 distance;

  priv = baseaudiopayload->priv;
  adapter = priv->adapter;

  basepayload = GST_RTP_BASE_PAYLOAD (baseaudiopayload);

  if (payload_len == -1)
    payload_len = gst_adapter_available (adapter);

  /* nothing to do, just return */
  if (payload_len == 0)
    return GST_FLOW_OK;

  if (timestamp == -1) {
    /* calculate the timestamp */
    timestamp = gst_adapter_prev_pts (adapter, &distance);

    GST_LOG_OBJECT (baseaudiopayload,
        "last timestamp %" GST_TIME_FORMAT ", distance %" G_GUINT64_FORMAT,
        GST_TIME_ARGS (timestamp), distance);

    if (GST_CLOCK_TIME_IS_VALID (timestamp) && distance > 0) {
      /* convert the number of bytes since the last timestamp to time and add to
       * the last seen timestamp */
      timestamp += priv->bytes_to_time (baseaudiopayload, distance);
    }
  }

  GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT,
      payload_len, GST_TIME_ARGS (timestamp));

  if (priv->buffer_list && gst_adapter_available_fast (adapter) >= payload_len) {
    GstBuffer *buffer;
    /* we can quickly take a buffer out of the adapter without having to copy
     * anything. */
    buffer = gst_adapter_take_buffer (adapter, payload_len);

    ret =
        gst_rtp_base_audio_payload_push_buffer (baseaudiopayload, buffer,
        timestamp);
  } else {
    GstBuffer *paybuf;
    CopyMetaData data;


    /* create buffer to hold the payload */
    outbuf = gst_rtp_base_payload_allocate_output_buffer (basepayload, 0, 0, 0);

    paybuf = gst_adapter_take_buffer_fast (adapter, payload_len);

    data.pay = baseaudiopayload;
    data.outbuf = outbuf;
    gst_buffer_foreach_meta (paybuf, foreach_metadata, &data);
    outbuf = gst_buffer_append (outbuf, paybuf);

    /* set metadata */
    gst_rtp_base_audio_payload_set_meta (baseaudiopayload, outbuf, payload_len,
        timestamp);

    ret = gst_rtp_base_payload_push (basepayload, outbuf);
  }

  return ret;
}
Ejemplo n.º 25
0
static GstFlowReturn
gst_rtp_asf_pay_handle_buffer (GstRTPBasePayload * rtppay, GstBuffer * buffer)
{
  GstRtpAsfPay *rtpasfpay = GST_RTP_ASF_PAY_CAST (rtppay);

  if (G_UNLIKELY (rtpasfpay->state == ASF_END)) {
    GST_LOG_OBJECT (rtpasfpay,
        "Dropping buffer as we already pushed all packets");
    gst_buffer_unref (buffer);
    return GST_FLOW_EOS;        /* we already finished our job */
  }

  /* receive headers 
   * we only accept if they are in a single buffer */
  if (G_UNLIKELY (rtpasfpay->state == ASF_NOT_STARTED)) {
    guint64 header_size;

    if (gst_buffer_get_size (buffer) < 24) {    /* guid+object size size */
      GST_ERROR_OBJECT (rtpasfpay,
          "Buffer too small, smaller than a Guid and object size");
      gst_buffer_unref (buffer);
      return GST_FLOW_ERROR;
    }

    header_size = gst_asf_match_and_peek_obj_size_buf (buffer,
        &(guids[ASF_HEADER_OBJECT_INDEX]));
    if (header_size > 0) {
      GST_DEBUG_OBJECT (rtpasfpay, "ASF header guid received, size %"
          G_GUINT64_FORMAT, header_size);

      if (gst_buffer_get_size (buffer) < header_size) {
        GST_ERROR_OBJECT (rtpasfpay, "Headers should be contained in a single"
            " buffer");
        gst_buffer_unref (buffer);
        return GST_FLOW_ERROR;
      } else {
        rtpasfpay->state = ASF_DATA_OBJECT;

        /* clear previous headers, if any */
        if (rtpasfpay->headers) {
          gst_buffer_unref (rtpasfpay->headers);
        }

        GST_DEBUG_OBJECT (rtpasfpay, "Storing headers");
        if (gst_buffer_get_size (buffer) == header_size) {
          rtpasfpay->headers = buffer;
          return GST_FLOW_OK;
        } else {
          /* headers are a subbuffer of thie buffer */
          GstBuffer *aux = gst_buffer_copy_region (buffer,
              GST_BUFFER_COPY_ALL, header_size,
              gst_buffer_get_size (buffer) - header_size);
          rtpasfpay->headers = gst_buffer_copy_region (buffer,
              GST_BUFFER_COPY_ALL, 0, header_size);
          gst_buffer_replace (&buffer, aux);
        }
      }
    } else {
      GST_ERROR_OBJECT (rtpasfpay, "Missing ASF header start");
      gst_buffer_unref (buffer);
      return GST_FLOW_ERROR;
    }
  }

  if (G_UNLIKELY (rtpasfpay->state == ASF_DATA_OBJECT)) {
    GstMapInfo map;

    if (gst_buffer_get_size (buffer) != ASF_DATA_OBJECT_SIZE) {
      GST_ERROR_OBJECT (rtpasfpay, "Received buffer of different size of "
          "the data object header");
      gst_buffer_unref (buffer);
      return GST_FLOW_ERROR;
    }

    gst_buffer_map (buffer, &map, GST_MAP_READ);
    if (gst_asf_match_guid (map.data, &(guids[ASF_DATA_OBJECT_INDEX]))) {
      gst_buffer_unmap (buffer, &map);
      GST_DEBUG_OBJECT (rtpasfpay, "Received data object header");
      rtpasfpay->headers = gst_buffer_append (rtpasfpay->headers, buffer);
      rtpasfpay->state = ASF_PACKETS;

      return gst_rtp_asf_pay_parse_headers (rtpasfpay);
    } else {
      gst_buffer_unmap (buffer, &map);
      GST_ERROR_OBJECT (rtpasfpay, "Unexpected object received (was expecting "
          "data object)");
      gst_buffer_unref (buffer);
      return GST_FLOW_ERROR;
    }
  }

  if (G_LIKELY (rtpasfpay->state == ASF_PACKETS)) {
    /* in broadcast mode we can't trust the packets count information
     * from the headers
     * We assume that if this is on broadcast mode it is a live stream
     * and we are going to keep receiving packets indefinitely
     */
    if (rtpasfpay->asfinfo.broadcast ||
        rtpasfpay->packets_count < rtpasfpay->asfinfo.packets_count) {
      GST_DEBUG_OBJECT (rtpasfpay, "Received packet %"
          G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT,
          rtpasfpay->packets_count, rtpasfpay->asfinfo.packets_count);
      rtpasfpay->packets_count++;
      return gst_rtp_asf_pay_handle_packet (rtpasfpay, buffer);
    } else {
      GST_INFO_OBJECT (rtpasfpay, "Packets ended");
      rtpasfpay->state = ASF_END;
      gst_buffer_unref (buffer);
      return GST_FLOW_EOS;
    }
  }

  gst_buffer_unref (buffer);
  return GST_FLOW_OK;
}
static GstFlowReturn
gst_rtp_mpa_pay_flush (GstRtpMPAPay * rtpmpapay)
{
  guint avail;
  GstBuffer *outbuf;
  GstFlowReturn ret;
  guint16 frag_offset;
  GstBufferList *list;

  /* the data available in the adapter is either smaller
   * than the MTU or bigger. In the case it is smaller, the complete
   * adapter contents can be put in one packet. In the case the
   * adapter has more than one MTU, we need to split the MPA data
   * over multiple packets. The frag_offset in each packet header
   * needs to be updated with the position in the MPA frame. */
  avail = gst_adapter_available (rtpmpapay->adapter);

  ret = GST_FLOW_OK;

  list =
      gst_buffer_list_new_sized (avail / (GST_RTP_BASE_PAYLOAD_MTU (rtpmpapay) -
          RTP_HEADER_LEN) + 1);

  frag_offset = 0;
  while (avail > 0) {
    guint towrite;
    guint8 *payload;
    guint payload_len;
    guint packet_len;
    GstRTPBuffer rtp = { NULL };
    GstBuffer *paybuf;

    /* this will be the total length of the packet */
    packet_len = gst_rtp_buffer_calc_packet_len (4 + avail, 0, 0);

    /* fill one MTU or all available bytes */
    towrite = MIN (packet_len, GST_RTP_BASE_PAYLOAD_MTU (rtpmpapay));

    /* this is the payload length */
    payload_len = gst_rtp_buffer_calc_payload_len (towrite, 0, 0);

    /* create buffer to hold the payload */
    outbuf = gst_rtp_buffer_new_allocate (4, 0, 0);

    gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);

    payload_len -= 4;

    gst_rtp_buffer_set_payload_type (&rtp, GST_RTP_PAYLOAD_MPA);

    /*
     *  0                   1                   2                   3
     *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     * |             MBZ               |          Frag_offset          |
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     */
    payload = gst_rtp_buffer_get_payload (&rtp);
    payload[0] = 0;
    payload[1] = 0;
    payload[2] = frag_offset >> 8;
    payload[3] = frag_offset & 0xff;

    avail -= payload_len;
    frag_offset += payload_len;

    if (avail == 0)
      gst_rtp_buffer_set_marker (&rtp, TRUE);

    gst_rtp_buffer_unmap (&rtp);

    paybuf = gst_adapter_take_buffer_fast (rtpmpapay->adapter, payload_len);
    gst_rtp_copy_meta (GST_ELEMENT_CAST (rtpmpapay), outbuf, paybuf,
        g_quark_from_static_string (GST_META_TAG_AUDIO_STR));
    outbuf = gst_buffer_append (outbuf, paybuf);

    GST_BUFFER_PTS (outbuf) = rtpmpapay->first_ts;
    GST_BUFFER_DURATION (outbuf) = rtpmpapay->duration;
    gst_buffer_list_add (list, outbuf);
  }

  ret = gst_rtp_base_payload_push_list (GST_RTP_BASE_PAYLOAD (rtpmpapay), list);

  return ret;
}
Ejemplo n.º 27
0
/*
 * Test if the parser pushes clean data properly.
 */
void
gst_parser_test_run (GstParserTest * test, GstCaps ** out_caps)
{
  buffer_verify_data_s vdata = { 0, 0, 0, NULL, 0, NULL, FALSE };
  GstElement *element;
  GstBuffer *buffer = NULL;
  GstCaps *src_caps;
  guint i, j, k;
  guint frames = 0, size = 0;

  element = setup_element (test->factory, test->sink_template, NULL,
      test->src_template, test->src_caps);

  /* push some setup headers */
  for (j = 0; j < G_N_ELEMENTS (test->headers) && test->headers[j].data; j++) {
    buffer = buffer_new (test->headers[j].data, test->headers[j].size);
    fail_unless_equals_int (gst_pad_push (srcpad, buffer), GST_FLOW_OK);
  }

  for (j = 0; j < 3; j++) {
    for (i = 0; i < test->series[j].num; i++) {
      /* sanity enforcing */
      for (k = 0; k < MAX (1, test->series[j].fpb); k++) {
        if (!k)
          buffer = buffer_new (test->series[j].data, test->series[j].size);
        else {
          buffer = gst_buffer_append (buffer,
              buffer_new (test->series[j].data, test->series[j].size));
        }
      }
      fail_unless_equals_int (gst_pad_push (srcpad, buffer), GST_FLOW_OK);
      if (j == 0)
        vdata.buffers_before_offset_skip++;
      else if (j == 1)
        vdata.offset_skip_amount += test->series[j].size * test->series[j].fpb;
      if (j != 1) {
        frames += test->series[j].fpb;
        size += test->series[j].size * test->series[j].fpb;
      }
    }
  }
  gst_pad_push_event (srcpad, gst_event_new_eos ());

  if (G_LIKELY (test->framed))
    fail_unless_equals_int (g_list_length (buffers) - test->discard, frames);

  /* if all frames are identical, do extended test,
   * otherwise only verify total data size */
  if (test->series[0].data && (!test->series[2].size ||
          (test->series[0].size == test->series[2].size && test->series[2].data
              && !memcmp (test->series[0].data, test->series[2].data,
                  test->series[0].size)))) {
    vdata.data_to_verify = test->series[0].data;
    vdata.data_to_verify_size = test->series[0].size;
    vdata.caps = test->sink_caps;
    vdata.discard = test->discard;
    vdata.no_metadata = test->no_metadata;
    g_list_foreach (buffers, buffer_verify_data, &vdata);
  } else {
    guint datasum = 0;

    g_list_foreach (buffers, buffer_count_size, &datasum);
    size -= test->dropped;
    fail_unless_equals_int (datasum, size);
  }

  src_caps = gst_pad_get_current_caps (sinkpad);
  GST_LOG ("output caps: %" GST_PTR_FORMAT, src_caps);

  if (test->sink_caps) {
    GST_LOG ("%" GST_PTR_FORMAT " = %" GST_PTR_FORMAT " ?", src_caps,
        test->sink_caps);
    fail_unless (gst_caps_is_equal (src_caps, test->sink_caps));
  }

  if (out_caps)
    *out_caps = src_caps;
  else
    gst_caps_unref (src_caps);

  cleanup_element (element);
}
Ejemplo n.º 28
0
static GstFlowReturn
gst_dvd_spu_subpic_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
  GstDVDSpu *dvdspu = (GstDVDSpu *) parent;
  GstFlowReturn ret = GST_FLOW_OK;
  gsize size;

  g_return_val_if_fail (dvdspu != NULL, GST_FLOW_ERROR);

  GST_INFO_OBJECT (dvdspu, "Have subpicture buffer with timestamp %"
      GST_TIME_FORMAT " and size %" G_GSIZE_FORMAT,
      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), gst_buffer_get_size (buf));

  DVD_SPU_LOCK (dvdspu);

  if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
    dvdspu->subp_seg.position = GST_BUFFER_TIMESTAMP (buf);
  }

  if (GST_BUFFER_IS_DISCONT (buf) && dvdspu->partial_spu) {
    gst_buffer_unref (dvdspu->partial_spu);
    dvdspu->partial_spu = NULL;
  }

  if (dvdspu->partial_spu != NULL) {
    if (GST_BUFFER_TIMESTAMP_IS_VALID (buf))
      GST_WARNING_OBJECT (dvdspu,
          "Joining subpicture buffer with timestamp to previous");
    dvdspu->partial_spu = gst_buffer_append (dvdspu->partial_spu, buf);
  } else {
    /* If we don't yet have a buffer, wait for one with a timestamp,
     * since that will avoid collecting the 2nd half of a partial buf */
    if (GST_BUFFER_TIMESTAMP_IS_VALID (buf))
      dvdspu->partial_spu = buf;
    else
      gst_buffer_unref (buf);
  }

  if (dvdspu->partial_spu == NULL)
    goto done;

  size = gst_buffer_get_size (dvdspu->partial_spu);

  switch (dvdspu->spu_input_type) {
    case SPU_INPUT_TYPE_VOBSUB:
      if (size >= 2) {
        guint8 header[2];
        guint16 packet_size;

        gst_buffer_extract (dvdspu->partial_spu, 0, header, 2);
        packet_size = GST_READ_UINT16_BE (header);
        if (packet_size == size) {
          submit_new_spu_packet (dvdspu, dvdspu->partial_spu);
          dvdspu->partial_spu = NULL;
        } else if (packet_size == 0) {
          GST_LOG_OBJECT (dvdspu, "Discarding empty SPU buffer");
          gst_buffer_unref (dvdspu->partial_spu);
          dvdspu->partial_spu = NULL;
        } else if (packet_size < size) {
          /* Somehow we collected too much - something is wrong. Drop the
           * packet entirely and wait for a new one */
          GST_DEBUG_OBJECT (dvdspu,
              "Discarding invalid SPU buffer of size %" G_GSIZE_FORMAT, size);

          gst_buffer_unref (dvdspu->partial_spu);
          dvdspu->partial_spu = NULL;
        } else {
          GST_LOG_OBJECT (dvdspu,
              "SPU buffer claims to be of size %u. Collected %" G_GSIZE_FORMAT
              " so far.", packet_size, size);
        }
      }
      break;
    case SPU_INPUT_TYPE_PGS:{
      /* Collect until we have a command buffer that ends exactly at the size
       * we've collected */
      guint8 packet_type;
      guint16 packet_size;
      GstMapInfo map;
      guint8 *ptr, *end;
      gboolean invalid = FALSE;

      gst_buffer_map (dvdspu->partial_spu, &map, GST_MAP_READ);

      ptr = map.data;
      end = ptr + map.size;

      /* FIXME: There's no need to walk the command set each time. We can set a
       * marker and resume where we left off next time */
      /* FIXME: Move the packet parsing and sanity checking into the format-specific modules */
      while (ptr != end) {
        if (ptr + 3 > end)
          break;
        packet_type = *ptr++;
        packet_size = GST_READ_UINT16_BE (ptr);
        ptr += 2;
        if (ptr + packet_size > end)
          break;
        ptr += packet_size;
        /* 0x80 is the END command for PGS packets */
        if (packet_type == 0x80 && ptr != end) {
          /* Extra cruft on the end of the packet -> assume invalid */
          invalid = TRUE;
          break;
        }
      }
      gst_buffer_unmap (dvdspu->partial_spu, &map);

      if (invalid) {
        gst_buffer_unref (dvdspu->partial_spu);
        dvdspu->partial_spu = NULL;
      } else if (ptr == end) {
        GST_DEBUG_OBJECT (dvdspu,
            "Have complete PGS packet of size %" G_GSIZE_FORMAT ". Enqueueing.",
            map.size);
        submit_new_spu_packet (dvdspu, dvdspu->partial_spu);
        dvdspu->partial_spu = NULL;
      }
      break;
    }
    default:
      GST_ERROR_OBJECT (dvdspu, "Input type not configured before SPU passing");
      goto caps_not_set;
  }

done:
  DVD_SPU_UNLOCK (dvdspu);

  return ret;

  /* ERRORS */
caps_not_set:
  {
    GST_ELEMENT_ERROR (dvdspu, RESOURCE, NO_SPACE_LEFT,
        (_("Subpicture format was not configured before data flow")), (NULL));
    ret = GST_FLOW_ERROR;
    goto done;
  }
}
Ejemplo n.º 29
0
static GstFlowReturn
gst_jasper_dec_chain (GstPad * pad, GstBuffer * buf)
{
  GstJasperDec *dec;
  GstFlowReturn ret = GST_FLOW_OK;
  GstClockTime ts;
  GstBuffer *outbuf = NULL;
  guint8 *data;
  guint size;
  gboolean decode;

  dec = GST_JASPER_DEC (GST_PAD_PARENT (pad));

  if (dec->fmt < 0)
    goto not_negotiated;

  ts = GST_BUFFER_TIMESTAMP (buf);

  GST_LOG_OBJECT (dec, "buffer with ts: %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));

  if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT))
    dec->discont = TRUE;

  decode = gst_jasper_dec_do_qos (dec, ts);

  /* FIXME: do clipping */

  if (G_UNLIKELY (!decode)) {
    dec->discont = TRUE;
    goto done;
  }

  /* strip possible prefix */
  if (dec->strip) {
    GstBuffer *tmp;

    tmp = gst_buffer_create_sub (buf, dec->strip,
        GST_BUFFER_SIZE (buf) - dec->strip);
    gst_buffer_copy_metadata (tmp, buf, GST_BUFFER_COPY_TIMESTAMPS);
    gst_buffer_unref (buf);
    buf = tmp;
  }
  /* preprend possible codec_data */
  if (dec->codec_data) {
    GstBuffer *tmp;

    tmp =
        gst_buffer_append (gst_buffer_ref (dec->codec_data),
        gst_buffer_ref (buf));
    gst_buffer_copy_metadata (tmp, buf, GST_BUFFER_COPY_TIMESTAMPS);
    gst_buffer_unref (buf);
    buf = tmp;
  }

  /* now really feed the data to decoder */
  data = GST_BUFFER_DATA (buf);
  size = GST_BUFFER_SIZE (buf);

  ret = gst_jasper_dec_get_picture (dec, data, size, &outbuf);

  if (outbuf) {
    gst_buffer_copy_metadata (outbuf, buf, GST_BUFFER_COPY_TIMESTAMPS);
    if (dec->discont) {
      GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
      dec->discont = FALSE;
    }

    if (ret == GST_FLOW_OK)
      ret = gst_pad_push (dec->srcpad, outbuf);
    else
      gst_buffer_unref (outbuf);
  }

done:
  gst_buffer_unref (buf);

  return ret;

  /* ERRORS */
not_negotiated:
  {
    GST_ELEMENT_ERROR (dec, CORE, NEGOTIATION, (NULL),
        ("format wasn't negotiated before chain function"));
    ret = GST_FLOW_NOT_NEGOTIATED;
    goto done;
  }
}
static GstFlowReturn
gst_rtp_klv_pay_handle_buffer (GstRTPBasePayload * basepayload, GstBuffer * buf)
{
  GstFlowReturn ret = GST_FLOW_OK;
  GstBufferList *list = NULL;
  GstRtpKlvPay *pay;
  GstMapInfo map;
  GstBuffer *outbuf = NULL;
  gsize offset;
  guint mtu, rtp_header_size, max_payload_size;

  pay = GST_RTP_KLV_PAY (basepayload);
  mtu = GST_RTP_BASE_PAYLOAD_MTU (basepayload);

  rtp_header_size = gst_rtp_buffer_calc_header_len (0);
  max_payload_size = mtu - rtp_header_size;

  gst_buffer_map (buf, &map, GST_MAP_READ);

  if (map.size == 0)
    goto done;

  /* KLV coding shall use and only use a fixed 16-byte SMPTE-administered
   * Universal Label, according to SMPTE 298M as Key (Rec. ITU R-BT.1653-1) */
  if (map.size < 16 || GST_READ_UINT32_BE (map.data) != 0x060E2B34)
    goto bad_input;

  if (map.size > max_payload_size)
    list = gst_buffer_list_new ();

  GST_LOG_OBJECT (pay, "%" G_GSIZE_FORMAT " bytes of data to payload",
      map.size);

  offset = 0;
  while (offset < map.size) {
    GstBuffer *payloadbuf;
    GstRTPBuffer rtp = { NULL };
    guint payload_size;
    guint bytes_left;

    bytes_left = map.size - offset;
    payload_size = MIN (bytes_left, max_payload_size);

    outbuf = gst_rtp_buffer_new_allocate (0, 0, 0);

    if (payload_size == bytes_left) {
      GST_LOG_OBJECT (pay, "last packet of KLV unit");
      gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
      gst_rtp_buffer_set_marker (&rtp, 1);
      gst_rtp_buffer_unmap (&rtp);
    }

    GST_LOG_OBJECT (pay, "packet with payload size %u", payload_size);

    gst_rtp_copy_meta (GST_ELEMENT_CAST (pay), outbuf, buf, 0);

    payloadbuf = gst_buffer_copy_region (buf, GST_BUFFER_COPY_MEMORY,
        offset, payload_size);

    /* join rtp header + payload memory parts */
    outbuf = gst_buffer_append (outbuf, payloadbuf);

    GST_BUFFER_PTS (outbuf) = GST_BUFFER_PTS (buf);
    GST_BUFFER_DTS (outbuf) = GST_BUFFER_DTS (buf);

    /* and add to list */
    if (list != NULL)
      gst_buffer_list_insert (list, -1, outbuf);

    offset += payload_size;
  }

done:

  gst_buffer_unmap (buf, &map);
  gst_buffer_unref (buf);

  if (list != NULL)
    ret = gst_rtp_base_payload_push_list (basepayload, list);
  else if (outbuf != NULL)
    ret = gst_rtp_base_payload_push (basepayload, outbuf);

  return ret;

/* ERRORS */
bad_input:
  {
    GST_ERROR_OBJECT (pay, "Input doesn't look like a KLV packet, ignoring");
    goto done;
  }
}