Пример #1
0
static void
gst_vtdec_enqueue_frame (void *data1, void *data2, VTStatus result,
    VTDecodeInfoFlags info, CVBufferRef cvbuf, CMTime pts, CMTime duration)
{
  GstVTDec *self = GST_VTDEC_CAST (data1);
  GstBuffer *src_buf = GST_BUFFER (data2);
  GstBuffer *buf;

  if (result != kVTSuccess) {
    GST_ERROR_OBJECT (self, "Error decoding frame %d", result);
    goto beach;
  }

  if (kVTDecodeInfo_FrameDropped & info) {
    GST_WARNING_OBJECT (self, "Frame dropped");
    goto beach;
  }

  buf = gst_core_video_buffer_new (cvbuf, &self->vinfo);
  gst_buffer_copy_into (buf, src_buf, GST_BUFFER_COPY_METADATA, 0, -1);
  GST_BUFFER_PTS (buf) = pts.value;
  GST_BUFFER_DURATION (buf) = duration.value;

  g_queue_push_head (self->cur_outbufs, buf);
  if (GST_BUFFER_PTS (src_buf) <= GST_BUFFER_DTS (src_buf)) {
    GST_LOG_OBJECT (self, "Flushing interal queue of buffers");
    self->flush = TRUE;
  } else {
    GST_LOG_OBJECT (self, "Queuing buffer");
  }

beach:
  return;
}
Пример #2
0
static GstFlowReturn
gst_dtls_enc_push (GstDtlsEnc * self, GstBuffer * buffer)
{
  GstDtlsBase *base = GST_DTLS_BASE (self);
  GstEvent *segment_event, *caps_event;
  gchar *stream_id;

  stream_id = gst_pad_get_stream_id (base->srcpad);

  if (stream_id == NULL) {
    stream_id = gst_pad_get_stream_id (base->sinkpad);

    if (stream_id == NULL) {
      stream_id = gst_pad_create_stream_id (base->srcpad,
          GST_ELEMENT (base), NULL);
    }

    gst_pad_push_event (base->srcpad, gst_event_new_stream_start (stream_id));
  }

  g_free (stream_id);

  caps_event = gst_pad_get_sticky_event (base->srcpad, GST_EVENT_CAPS, 0);

  if (caps_event == NULL) {
    GstCaps *caps = gst_caps_from_string ("application/x-dtls");

    caps_event = gst_event_new_caps (caps);
    gst_caps_unref (caps);

    gst_pad_push_event (base->srcpad, caps_event);
  } else {
    gst_event_unref (caps_event);
  }

  segment_event = gst_pad_get_sticky_event (base->srcpad, GST_EVENT_SEGMENT, 0);

  if (segment_event == NULL) {
    GstSegment *segment = gst_segment_new ();

    gst_segment_init (segment, GST_FORMAT_BYTES);
    segment_event = gst_event_new_segment (segment);
    gst_segment_free (segment);

    gst_pad_push_event (base->srcpad, segment_event);
  } else {
    gst_event_unref (segment_event);
  }

  GST_OBJECT_LOCK (self);
  if (self->src_buffer && self->running_thread == g_thread_self ()) {
    g_assert (gst_buffer_get_size (buffer) != 181);
    gst_buffer_copy_into (buffer, self->src_buffer, GST_BUFFER_COPY_METADATA, 0,
        -1);
  }
  GST_OBJECT_UNLOCK (self);

  return gst_pad_push (base->srcpad, buffer);
}
Пример #3
0
GstBuffer *
mpegtsmux_prepare_teletext (GstBuffer * buf, MpegTsPadData * pad_data,
    MpegTsMux * mux)
{
  GstBuffer *out_buf;
  guint8 *data, *odata;
  gint size, stuff;
  gboolean add_id;
  GstMapInfo map, omap;

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

  /* check if leading data_identifier byte is already present,
   * if not increase size since it will need to be added */
  if (data[0] < 0x10 || data[0] > 0x1F) {
    size += 1;
    add_id = TRUE;
  }

  if (size <= 184 - 45) {
    stuff = 184 - 45 - size;
  } else {
    stuff = size - (184 - 45);
    stuff = 184 - (stuff % 184);
  }
  if (G_UNLIKELY (stuff == 1))
    stuff += 184;

  GST_DEBUG_OBJECT (mux, "Preparing teletext buffer for output");

  out_buf = gst_buffer_new_and_alloc (size + stuff);
  gst_buffer_copy_into (out_buf, buf,
      GST_BUFFER_COPY_METADATA | GST_BUFFER_COPY_TIMESTAMPS, 0, 0);

  /* copy data */
  gst_buffer_map (out_buf, &omap, GST_MAP_WRITE);
  odata = omap.data;
  /* add data_identifier if needed */
  if (add_id) {
    *odata = 0x10;
    memcpy (odata + 1, data, size - 1);
  } else {
    memcpy (odata, data, size);
  }

  /* add stuffing data_unit */
  odata += size;
  *odata++ = 0xFF;
  *odata = stuff;

  gst_buffer_unmap (buf, &map);
  gst_buffer_unmap (out_buf, &omap);

  return out_buf;
}
Пример #4
0
static GstFlowReturn
gst_jp2k_decimator_decimate_jpc (GstJP2kDecimator * self, GstBuffer * inbuf,
    GstBuffer ** outbuf_)
{
  GstBuffer *outbuf = NULL;
  GstFlowReturn ret = GST_FLOW_OK;
  GstMapInfo info;
  GstByteReader reader;
  GstByteWriter writer;
  MainHeader main_header;


  if (!gst_buffer_map (inbuf, &info, GST_MAP_READ)) {
    GST_ELEMENT_ERROR (self, STREAM, WRONG_TYPE, ("Unable to map memory"),
        (NULL));
    gst_buffer_unref (inbuf);
    return GST_FLOW_ERROR;
  }

  gst_byte_reader_init (&reader, info.data, info.size);
  gst_byte_writer_init_with_size (&writer, gst_buffer_get_size (inbuf), FALSE);

  /* main header */
  memset (&main_header, 0, sizeof (MainHeader));
  ret = parse_main_header (self, &reader, &main_header);
  if (ret != GST_FLOW_OK)
    goto done;

  ret = decimate_main_header (self, &main_header);
  if (ret != GST_FLOW_OK)
    goto done;

  ret = write_main_header (self, &writer, &main_header);
  if (ret != GST_FLOW_OK)
    goto done;

  outbuf = gst_byte_writer_reset_and_get_buffer (&writer);
  gst_buffer_copy_into (outbuf, inbuf, GST_BUFFER_COPY_METADATA, 0, -1);

  GST_DEBUG_OBJECT (self,
      "Decimated buffer from %" G_GSIZE_FORMAT " bytes to %" G_GSIZE_FORMAT
      " bytes (%.2lf%%)",
      gst_buffer_get_size (inbuf), gst_buffer_get_size (outbuf),
      (100 * gst_buffer_get_size (outbuf)) /
      ((gdouble) gst_buffer_get_size (inbuf)));

done:
  gst_buffer_unmap (inbuf, &info);

  *outbuf_ = outbuf;
  reset_main_header (self, &main_header);
  gst_buffer_unref (inbuf);

  return ret;
}
Пример #5
0
static GstFlowReturn
gst_ffmpegdeinterlace_chain (GstPad * pad, GstObject * parent,
    GstBuffer * inbuf)
{
  GstFFMpegDeinterlace *deinterlace = GST_FFMPEGDEINTERLACE (parent);
  GstBuffer *outbuf = NULL;
  GstFlowReturn result;
  GstMapInfo from_map, to_map;

  GST_OBJECT_LOCK (deinterlace);
  if (deinterlace->reconfigure) {
    if (deinterlace->new_mode != -1)
      deinterlace->mode = deinterlace->new_mode;
    deinterlace->new_mode = -1;

    deinterlace->reconfigure = FALSE;
    GST_OBJECT_UNLOCK (deinterlace);
    if (gst_pad_has_current_caps (deinterlace->srcpad)) {
      GstCaps *caps;

      caps = gst_pad_get_current_caps (deinterlace->sinkpad);
      gst_ffmpegdeinterlace_sink_setcaps (deinterlace->sinkpad, caps);
      gst_caps_unref (caps);
    }
  } else {
    GST_OBJECT_UNLOCK (deinterlace);
  }

  if (deinterlace->passthrough)
    return gst_pad_push (deinterlace->srcpad, inbuf);

  outbuf = gst_buffer_new_and_alloc (deinterlace->to_size);

  gst_buffer_map (inbuf, &from_map, GST_MAP_READ);
  gst_ffmpeg_avpicture_fill (&deinterlace->from_frame, from_map.data,
      deinterlace->pixfmt, deinterlace->width, deinterlace->height);

  gst_buffer_map (outbuf, &to_map, GST_MAP_WRITE);
  gst_ffmpeg_avpicture_fill (&deinterlace->to_frame, to_map.data,
      deinterlace->pixfmt, deinterlace->width, deinterlace->height);

  avpicture_deinterlace (&deinterlace->to_frame, &deinterlace->from_frame,
      deinterlace->pixfmt, deinterlace->width, deinterlace->height);
  gst_buffer_unmap (outbuf, &to_map);
  gst_buffer_unmap (inbuf, &from_map);

  gst_buffer_copy_into (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS, 0, -1);

  result = gst_pad_push (deinterlace->srcpad, outbuf);

  gst_buffer_unref (inbuf);

  return result;
}
Пример #6
0
GstBuffer* createGstBuffer(GstBuffer* buffer)
{
    gsize bufferSize = gst_buffer_get_size(buffer);
    GstBuffer* newBuffer = gst_buffer_new_and_alloc(bufferSize);

    if (!newBuffer)
        return 0;

    gst_buffer_copy_into(newBuffer, buffer, static_cast<GstBufferCopyFlags>(GST_BUFFER_COPY_METADATA), 0, bufferSize);
    return newBuffer;
}
Пример #7
0
/**
 * gst_adapter_get_buffer_fast:
 * @adapter:  a #GstAdapter
 * @nbytes: the number of bytes to get
 *
 * Returns a #GstBuffer containing the first @nbytes of the @adapter, but
 * does not flush them from the adapter. See gst_adapter_take_buffer_fast()
 * for details.
 *
 * Caller owns a reference to the returned buffer. gst_buffer_unref() after
 * usage.
 *
 * Free-function: gst_buffer_unref
 *
 * Returns: (transfer full) (nullable): a #GstBuffer containing the first
 *     @nbytes of the adapter, or %NULL if @nbytes bytes are not available.
 *     gst_buffer_unref() when no longer needed.
 *
 * Since: 1.6
 */
GstBuffer *
gst_adapter_get_buffer_fast (GstAdapter * adapter, gsize nbytes)
{
  GstBuffer *buffer = NULL;
  GstBuffer *cur;
  GSList *item;
  gsize skip;
  gsize left = nbytes;

  g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
  g_return_val_if_fail (nbytes > 0, NULL);

  GST_LOG_OBJECT (adapter, "getting buffer of %" G_GSIZE_FORMAT " bytes",
      nbytes);

  /* we don't have enough data, return NULL. This is unlikely
   * as one usually does an _available() first instead of grabbing a
   * random size. */
  if (G_UNLIKELY (nbytes > adapter->size))
    return NULL;

  skip = adapter->skip;
  cur = adapter->buflist->data;

  if (skip == 0 && gst_buffer_get_size (cur) == nbytes) {
    GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes"
        " as head buffer", nbytes);
    buffer = gst_buffer_ref (cur);
    goto done;
  }

  for (item = adapter->buflist; item && left > 0; item = item->next) {
    gsize size, cur_size;

    cur = item->data;
    cur_size = gst_buffer_get_size (cur);
    size = MIN (cur_size - skip, left);

    GST_LOG_OBJECT (adapter, "appending %" G_GSIZE_FORMAT " bytes"
        " via region copy", size);
    if (buffer)
      gst_buffer_copy_into (buffer, cur,
          GST_BUFFER_COPY_MEMORY | GST_BUFFER_COPY_META, skip, size);
    else
      buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, size);
    skip = 0;
    left -= size;
  }

done:

  return buffer;
}
Пример #8
0
void GStreamerReader::CopyIntoImageBuffer(GstBuffer* aBuffer,
                                          GstBuffer** aOutBuffer,
                                          nsRefPtr<PlanarYCbCrImage> &image)
{
  *aOutBuffer = gst_buffer_new_allocate(mAllocator, gst_buffer_get_size(aBuffer), nullptr);
  GstMemory *mem = gst_buffer_peek_memory(*aOutBuffer, 0);
  GstMapInfo map_info;
  gst_memory_map(mem, &map_info, GST_MAP_WRITE);
  gst_buffer_extract(aBuffer, 0, map_info.data, gst_buffer_get_size(aBuffer));
  gst_memory_unmap(mem, &map_info);

  /* create a new gst buffer with the newly created memory and copy the
   * metadata over from the incoming buffer */
  gst_buffer_copy_into(*aOutBuffer, aBuffer,
      (GstBufferCopyFlags)(GST_BUFFER_COPY_METADATA), 0, -1);
  image = GetImageFromBuffer(*aOutBuffer);
}
Пример #9
0
static void
gst_vtdec_enqueue_frame (void *data, gsize unk1, VTStatus result, gsize unk2,
    CVBufferRef cvbuf)
{
  GstVTDec *self = GST_VTDEC_CAST (data);
  GstBuffer *buf;

  if (result != kVTSuccess)
    goto beach;

  buf = gst_core_video_buffer_new (self->ctx, cvbuf, &self->vinfo);
  gst_buffer_copy_into (buf, self->cur_inbuf, GST_BUFFER_COPY_METADATA, 0, -1);

  g_ptr_array_add (self->cur_outbufs, buf);

beach:
  return;
}
static GstFlowReturn
gst_vorbis_tag_parse_packet (GstVorbisParse * parse, GstBuffer * buffer)
{
  GstTagList *old_tags, *new_tags;
  const GstTagList *user_tags;
  GstVorbisTag *tagger;
  gchar *encoder = NULL;
  GstBuffer *new_buf;
  GstMapInfo map;
  gboolean do_parse = FALSE;

  gst_buffer_map (buffer, &map, GST_MAP_READ);
  /* just pass everything except the comments packet */
  if (map.size >= 1 && map.data[0] != 0x03)
    do_parse = TRUE;
  gst_buffer_unmap (buffer, &map);

  if (do_parse) {
    return GST_VORBIS_PARSE_CLASS (parent_class)->parse_packet (parse, buffer);
  }

  tagger = GST_VORBIS_TAG (parse);

  old_tags =
      gst_tag_list_from_vorbiscomment_buffer (buffer, (guint8 *) "\003vorbis",
      7, &encoder);
  user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (tagger));

  /* build new tag list */
  new_tags = gst_tag_list_merge (user_tags, old_tags,
      gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (tagger)));
  gst_tag_list_unref (old_tags);

  new_buf =
      gst_tag_list_to_vorbiscomment_buffer (new_tags, (guint8 *) "\003vorbis",
      7, encoder);
  gst_buffer_copy_into (new_buf, buffer, GST_BUFFER_COPY_TIMESTAMPS, 0, -1);

  gst_tag_list_unref (new_tags);
  g_free (encoder);
  gst_buffer_unref (buffer);

  return GST_VORBIS_PARSE_CLASS (parent_class)->parse_packet (parse, new_buf);
}
Пример #11
0
GstBuffer* createGstBuffer(GstBuffer* buffer)
{
#ifndef GST_API_VERSION_1
    GstBuffer* newBuffer = gst_buffer_try_new_and_alloc(GST_BUFFER_SIZE(buffer));
#else
    gsize bufferSize = gst_buffer_get_size(buffer);
    GstBuffer* newBuffer = gst_buffer_new_and_alloc(bufferSize);
#endif

    if (!newBuffer)
        return 0;

#ifndef GST_API_VERSION_1
    gst_buffer_copy_metadata(newBuffer, buffer, static_cast<GstBufferCopyFlags>(GST_BUFFER_COPY_ALL));
#else
    gst_buffer_copy_into(newBuffer, buffer, static_cast<GstBufferCopyFlags>(GST_BUFFER_COPY_METADATA), 0, bufferSize);
#endif
    return newBuffer;
}
Пример #12
0
static gboolean
buffer_list_copy_data (GstBuffer ** buf, guint idx, gpointer data)
{
  GstBuffer *dest = data;
  guint num, i;

  if (idx == 0)
    gst_buffer_copy_into (dest, *buf, GST_BUFFER_COPY_METADATA, 0, -1);

  num = gst_buffer_n_memory (*buf);
  for (i = 0; i < num; ++i) {
    GstMemory *mem;

    mem = gst_buffer_get_memory (*buf, i);
    gst_buffer_append_memory (dest, mem);
  }

  return TRUE;
}
static GstBuffer *
gst_directsound_sink_payload (GstAudioBaseSink * sink, GstBuffer * buf)
{
  if (gst_directsound_sink_is_spdif_format (&sink->ringbuffer->spec)) {
    gint framesize = gst_audio_iec61937_frame_size (&sink->ringbuffer->spec);
    GstBuffer *out;
    GstMapInfo infobuf, infoout;
    gboolean success;

    if (framesize <= 0)
      return NULL;

    out = gst_buffer_new_and_alloc (framesize);

    if (!gst_buffer_map (buf, &infobuf, GST_MAP_READWRITE)) {
      gst_buffer_unref (out);
      return NULL;
    }
    if (!gst_buffer_map (out, &infoout, GST_MAP_READWRITE)) {
      gst_buffer_unmap (buf, &infobuf);
      gst_buffer_unref (out);
      return NULL;
    }
    success = gst_audio_iec61937_payload (infobuf.data, infobuf.size,
        infoout.data, infoout.size, &sink->ringbuffer->spec, G_BYTE_ORDER);
    if (!success) {
      gst_buffer_unmap (out, &infoout);
      gst_buffer_unmap (buf, &infobuf);
      gst_buffer_unref (out);
      return NULL;
    }

    gst_buffer_copy_into (out, buf, GST_BUFFER_COPY_ALL, 0, -1);
    /* Fix endianness */
    _swab ((gchar *) infoout.data, (gchar *) infoout.data, infobuf.size);
    gst_buffer_unmap (out, &infoout);
    gst_buffer_unmap (buf, &infobuf);
    return out;
  } else
    return gst_buffer_ref (buf);
}
Пример #14
0
/* chain function
 * this function does the actual processing
 */
static GstFlowReturn
gst_edge_detect_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
  GstEdgeDetect *filter;
  GstBuffer *outbuf;
  GstMapInfo in_info;
  GstMapInfo out_info;

  filter = GST_EDGE_DETECT (parent);

  buf = gst_buffer_make_writable (buf);
  gst_buffer_map (buf, &in_info, GST_MAP_WRITE);
  filter->cvImage->imageData = (char *) in_info.data;

  cvCvtColor (filter->cvImage, filter->cvGray, CV_RGB2GRAY);
  cvSmooth (filter->cvGray, filter->cvEdge, CV_BLUR, 3, 3, 0, 0);
  cvNot (filter->cvGray, filter->cvEdge);
  cvCanny (filter->cvGray, filter->cvEdge, filter->threshold1,
      filter->threshold2, filter->aperture);

  cvZero (filter->cvCEdge);
  if (filter->mask) {
    cvCopy (filter->cvImage, filter->cvCEdge, filter->cvEdge);
  } else {
    cvCvtColor (filter->cvEdge, filter->cvCEdge, CV_GRAY2RGB);
  }

  outbuf = gst_buffer_new_and_alloc (filter->cvCEdge->imageSize);
  gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);

  gst_buffer_map (outbuf, &out_info, GST_MAP_WRITE);
  memcpy (out_info.data, filter->cvCEdge->imageData,
      gst_buffer_get_size (outbuf));

  gst_buffer_unmap (buf, &in_info);
  gst_buffer_unmap (outbuf, &out_info);
  gst_buffer_unref (buf);
  return gst_pad_push (filter->srcpad, outbuf);
}
Пример #15
0
static GstFlowReturn
gst_gl_stereo_mix_aggregate_frames (GstVideoAggregator * vagg,
    GstBuffer * outbuf)
{
  GstGLStereoMix *mix = GST_GL_STEREO_MIX (vagg);
  /* If we're operating in frame-by-frame mode, push
   * the primary view now, and let the parent class
   * push the remaining auxilliary view */
  if (GST_VIDEO_INFO_MULTIVIEW_MODE (&vagg->info) ==
      GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME) {
    /* Transfer the timestamps video-agg put on the aux buffer */
    gst_buffer_copy_into (mix->primary_out, outbuf,
        GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
    gst_aggregator_finish_buffer (GST_AGGREGATOR (vagg), mix->primary_out);
    mix->primary_out = NULL;

    /* And actually, we don't want timestamps on the aux buffer */
    GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
    GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
  }
  return GST_FLOW_OK;
}
Пример #16
0
static GstBuffer *
gst_alsasink_payload (GstAudioBaseSink * sink, GstBuffer * buf)
{
  GstAlsaSink *alsa;

  alsa = GST_ALSA_SINK (sink);

  if (alsa->iec958) {
    GstBuffer *out;
    gint framesize;
    GstMapInfo iinfo, oinfo;

    framesize = gst_audio_iec61937_frame_size (&sink->ringbuffer->spec);
    if (framesize <= 0)
      return NULL;

    out = gst_buffer_new_and_alloc (framesize);

    gst_buffer_map (buf, &iinfo, GST_MAP_READ);
    gst_buffer_map (out, &oinfo, GST_MAP_WRITE);

    if (!gst_audio_iec61937_payload (iinfo.data, iinfo.size,
            oinfo.data, oinfo.size, &sink->ringbuffer->spec, G_BIG_ENDIAN)) {
      gst_buffer_unmap (buf, &iinfo);
      gst_buffer_unmap (out, &oinfo);
      gst_buffer_unref (out);
      return NULL;
    }

    gst_buffer_unmap (buf, &iinfo);
    gst_buffer_unmap (out, &oinfo);

    gst_buffer_copy_into (out, buf, GST_BUFFER_COPY_METADATA, 0, -1);
    return out;
  }

  return gst_buffer_ref (buf);
}
Пример #17
0
static VTStatus
gst_vtenc_enqueue_buffer (void *data, int a2, int a3, int a4,
    CMSampleBufferRef sbuf, int a6, int a7)
{
  GstVTEnc *self = data;
  gboolean is_keyframe;
  GstBuffer *buf;

  /* This may happen if we don't have enough bitrate */
  if (sbuf == NULL)
    goto beach;

  is_keyframe = gst_vtenc_buffer_is_keyframe (self, sbuf);
  if (self->expect_keyframe) {
    if (!is_keyframe)
      goto beach;
    CFDictionaryRemoveValue (self->options,
        *(self->ctx->vt->kVTEncodeFrameOptionKey_ForceKeyFrame));
  }
  self->expect_keyframe = FALSE;

  /* We are dealing with block buffers here, so we don't need
   * to enable the use of the video meta API on the core media buffer */
  buf = gst_core_media_buffer_new (sbuf, FALSE);
  gst_buffer_copy_into (buf, self->cur_inbuf, GST_BUFFER_COPY_TIMESTAMPS,
      0, -1);
  if (is_keyframe) {
    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
  } else {
    GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
  }

  g_ptr_array_add (self->cur_outbufs, buf);

beach:
  return kVTSuccess;
}
Пример #18
0
static GstBuffer *
gst_osx_audio_sink_sink_payload (GstAudioBaseSink * sink, GstBuffer * buf)
{
  if (RINGBUFFER_IS_SPDIF (sink->ringbuffer->spec.type)) {
    gint framesize = gst_audio_iec61937_frame_size (&sink->ringbuffer->spec);
    GstBuffer *out;
    GstMapInfo inmap, outmap;
    gboolean res;

    if (framesize <= 0)
      return NULL;

    out = gst_buffer_new_and_alloc (framesize);

    gst_buffer_map (buf, &inmap, GST_MAP_READ);
    gst_buffer_map (out, &outmap, GST_MAP_WRITE);

    /* FIXME: the endianness needs to be queried and then set */
    res = gst_audio_iec61937_payload (inmap.data, inmap.size,
        outmap.data, outmap.size, &sink->ringbuffer->spec, G_BIG_ENDIAN);

    gst_buffer_unmap (buf, &inmap);
    gst_buffer_unmap (out, &outmap);

    if (!res) {
      gst_buffer_unref (out);
      return NULL;
    }

    gst_buffer_copy_into (out, buf, GST_BUFFER_COPY_METADATA, 0, -1);
    return out;

  } else {
    return gst_buffer_ref (buf);
  }
}
Пример #19
0
static GstFlowReturn
gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
  GstShmSink *self = GST_SHM_SINK (bsink);
  int rv = 0;
  GstMapInfo map;
  gboolean need_new_memory = FALSE;
  GstFlowReturn ret = GST_FLOW_OK;
  GstMemory *memory = NULL;
  GstBuffer *sendbuf = NULL;

  GST_OBJECT_LOCK (self);
  while (self->wait_for_connection && !self->clients) {
    g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self));
    if (self->unlock)
      goto flushing;
  }

  while (!gst_shm_sink_can_render (self, GST_BUFFER_TIMESTAMP (buf))) {
    g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self));
    if (self->unlock)
      goto flushing;
  }


  if (gst_buffer_n_memory (buf) > 1) {
    GST_LOG_OBJECT (self, "Buffer %p has %d GstMemory, we only support a single"
        " one, need to do a memcpy", buf, gst_buffer_n_memory (buf));
    need_new_memory = TRUE;
  } else {
    memory = gst_buffer_peek_memory (buf, 0);

    if (memory->allocator != GST_ALLOCATOR (self->allocator)) {
      need_new_memory = TRUE;
      GST_LOG_OBJECT (self, "Memory in buffer %p was not allocated by "
          "%" GST_PTR_FORMAT ", will memcpy", buf, memory->allocator);
    }
  }

  if (need_new_memory) {
    if (gst_buffer_get_size (buf) > sp_writer_get_max_buf_size (self->pipe)) {
      gsize area_size = sp_writer_get_max_buf_size (self->pipe);
      GST_OBJECT_UNLOCK (self);
      GST_ELEMENT_ERROR (self, RESOURCE, NO_SPACE_LEFT,
          ("Shared memory area is too small"),
          ("Shared memory area of size %" G_GSIZE_FORMAT " is smaller than"
              "buffer of size %" G_GSIZE_FORMAT, area_size,
              gst_buffer_get_size (buf)));
      return GST_FLOW_ERROR;
    }

    while ((memory =
            gst_shm_sink_allocator_alloc_locked (self->allocator,
                gst_buffer_get_size (buf), &self->params)) == NULL) {
      g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self));
      if (self->unlock)
        goto flushing;
    }

    while (self->wait_for_connection && !self->clients) {
      g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self));
      if (self->unlock) {
        gst_memory_unref (memory);
        GST_OBJECT_UNLOCK (self);
        return GST_FLOW_FLUSHING;
      }
    }

    gst_memory_map (memory, &map, GST_MAP_WRITE);
    gst_buffer_extract (buf, 0, map.data, map.size);
    gst_memory_unmap (memory, &map);

    sendbuf = gst_buffer_new ();
    gst_buffer_copy_into (sendbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
    gst_buffer_append_memory (sendbuf, memory);
  } else {
    sendbuf = gst_buffer_ref (buf);
  }

  gst_buffer_map (sendbuf, &map, GST_MAP_READ);
  /* Make the memory readonly as of now as we've sent it to the other side
   * We know it's not mapped for writing anywhere as we just mapped it for
   * reading
   */

  rv = sp_writer_send_buf (self->pipe, (char *) map.data, map.size, sendbuf);

  gst_buffer_unmap (sendbuf, &map);

  GST_OBJECT_UNLOCK (self);

  if (rv == 0) {
    GST_DEBUG_OBJECT (self, "No clients connected, unreffing buffer");
    gst_buffer_unref (sendbuf);
  } else if (rv == -1) {
    GST_ELEMENT_ERROR (self, STREAM, FAILED, ("Invalid allocated buffer"),
        ("The shmpipe library rejects our buffer, this is a bug"));
    ret = GST_FLOW_ERROR;
  }

  /* If we allocated our own memory, then unmap it */

  return ret;

flushing:
  GST_OBJECT_UNLOCK (self);
  return GST_FLOW_FLUSHING;
}
static GstFlowReturn
gst_y4m_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
{
  GstY4mDec *y4mdec;
  int n_avail;
  GstFlowReturn flow_ret = GST_FLOW_OK;
#define MAX_HEADER_LENGTH 80
  char header[MAX_HEADER_LENGTH];
  int i;
  int len;

  y4mdec = GST_Y4M_DEC (parent);

  GST_DEBUG_OBJECT (y4mdec, "chain");

  if (GST_BUFFER_IS_DISCONT (buffer)) {
    GST_DEBUG ("got discont");
    gst_adapter_clear (y4mdec->adapter);
  }

  gst_adapter_push (y4mdec->adapter, buffer);
  n_avail = gst_adapter_available (y4mdec->adapter);

  if (!y4mdec->have_header) {
    gboolean ret;
    GstCaps *caps;
    GstQuery *query;

    if (n_avail < MAX_HEADER_LENGTH)
      return GST_FLOW_OK;

    gst_adapter_copy (y4mdec->adapter, (guint8 *) header, 0, MAX_HEADER_LENGTH);

    header[MAX_HEADER_LENGTH - 1] = 0;
    for (i = 0; i < MAX_HEADER_LENGTH; i++) {
      if (header[i] == 0x0a)
        header[i] = 0;
    }

    ret = gst_y4m_dec_parse_header (y4mdec, header);
    if (!ret) {
      GST_ELEMENT_ERROR (y4mdec, STREAM, DECODE,
          ("Failed to parse YUV4MPEG header"), (NULL));
      return GST_FLOW_ERROR;
    }

    y4mdec->header_size = strlen (header) + 1;
    gst_adapter_flush (y4mdec->adapter, y4mdec->header_size);

    caps = gst_video_info_to_caps (&y4mdec->info);
    ret = gst_pad_set_caps (y4mdec->srcpad, caps);

    query = gst_query_new_allocation (caps, FALSE);
    y4mdec->video_meta = FALSE;

    if (y4mdec->pool) {
      gst_buffer_pool_set_active (y4mdec->pool, FALSE);
      gst_object_unref (y4mdec->pool);
    }
    y4mdec->pool = NULL;

    if (gst_pad_peer_query (y4mdec->srcpad, query)) {
      y4mdec->video_meta =
          gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);

      /* We only need a pool if we need to do stride conversion for downstream */
      if (!y4mdec->video_meta && memcmp (&y4mdec->info, &y4mdec->out_info,
              sizeof (y4mdec->info)) != 0) {
        GstBufferPool *pool = NULL;
        GstAllocator *allocator = NULL;
        GstAllocationParams params;
        GstStructure *config;
        guint size, min, max;

        if (gst_query_get_n_allocation_params (query) > 0) {
          gst_query_parse_nth_allocation_param (query, 0, &allocator, &params);
        } else {
          allocator = NULL;
          gst_allocation_params_init (&params);
        }

        if (gst_query_get_n_allocation_pools (query) > 0) {
          gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min,
              &max);
          size = MAX (size, y4mdec->out_info.size);
        } else {
          pool = NULL;
          size = y4mdec->out_info.size;
          min = max = 0;
        }

        if (pool == NULL) {
          pool = gst_video_buffer_pool_new ();
        }

        config = gst_buffer_pool_get_config (pool);
        gst_buffer_pool_config_set_params (config, caps, size, min, max);
        gst_buffer_pool_config_set_allocator (config, allocator, &params);
        gst_buffer_pool_set_config (pool, config);

        if (allocator)
          gst_object_unref (allocator);

        y4mdec->pool = pool;
      }
    } else if (memcmp (&y4mdec->info, &y4mdec->out_info,
            sizeof (y4mdec->info)) != 0) {
      GstBufferPool *pool;
      GstStructure *config;

      /* No pool, create our own if we need to do stride conversion */
      pool = gst_video_buffer_pool_new ();
      config = gst_buffer_pool_get_config (pool);
      gst_buffer_pool_config_set_params (config, caps, y4mdec->out_info.size, 0,
          0);
      gst_buffer_pool_set_config (pool, config);
      y4mdec->pool = pool;
    }
    if (y4mdec->pool) {
      gst_buffer_pool_set_active (y4mdec->pool, TRUE);
    }
    gst_query_unref (query);
    gst_caps_unref (caps);
    if (!ret) {
      GST_DEBUG_OBJECT (y4mdec, "Couldn't set caps on src pad");
      return GST_FLOW_ERROR;
    }

    y4mdec->have_header = TRUE;
  }

  if (y4mdec->have_new_segment) {
    GstEvent *event;
    GstClockTime start = gst_y4m_dec_bytes_to_timestamp (y4mdec,
        y4mdec->segment.start);
    GstClockTime stop = gst_y4m_dec_bytes_to_timestamp (y4mdec,
        y4mdec->segment.stop);
    GstClockTime time = gst_y4m_dec_bytes_to_timestamp (y4mdec,
        y4mdec->segment.time);
    GstSegment seg;

    gst_segment_init (&seg, GST_FORMAT_TIME);
    seg.start = start;
    seg.stop = stop;
    seg.time = time;
    event = gst_event_new_segment (&seg);

    gst_pad_push_event (y4mdec->srcpad, event);
    //gst_event_unref (event);

    y4mdec->have_new_segment = FALSE;
    y4mdec->frame_index = gst_y4m_dec_bytes_to_frames (y4mdec,
        y4mdec->segment.time);
    GST_DEBUG ("new frame_index %d", y4mdec->frame_index);

  }

  while (1) {
    n_avail = gst_adapter_available (y4mdec->adapter);
    if (n_avail < MAX_HEADER_LENGTH)
      break;

    gst_adapter_copy (y4mdec->adapter, (guint8 *) header, 0, MAX_HEADER_LENGTH);
    header[MAX_HEADER_LENGTH - 1] = 0;
    for (i = 0; i < MAX_HEADER_LENGTH; i++) {
      if (header[i] == 0x0a)
        header[i] = 0;
    }
    if (memcmp (header, "FRAME", 5) != 0) {
      GST_ELEMENT_ERROR (y4mdec, STREAM, DECODE,
          ("Failed to parse YUV4MPEG frame"), (NULL));
      flow_ret = GST_FLOW_ERROR;
      break;
    }

    len = strlen (header);
    if (n_avail < y4mdec->info.size + len + 1) {
      /* not enough data */
      GST_DEBUG ("not enough data for frame %d < %" G_GSIZE_FORMAT,
          n_avail, y4mdec->info.size + len + 1);
      break;
    }

    gst_adapter_flush (y4mdec->adapter, len + 1);

    buffer = gst_adapter_take_buffer (y4mdec->adapter, y4mdec->info.size);

    GST_BUFFER_TIMESTAMP (buffer) =
        gst_y4m_dec_frames_to_timestamp (y4mdec, y4mdec->frame_index);
    GST_BUFFER_DURATION (buffer) =
        gst_y4m_dec_frames_to_timestamp (y4mdec, y4mdec->frame_index + 1) -
        GST_BUFFER_TIMESTAMP (buffer);

    y4mdec->frame_index++;

    if (y4mdec->video_meta) {
      gst_buffer_add_video_meta_full (buffer, 0, y4mdec->info.finfo->format,
          y4mdec->info.width, y4mdec->info.height, y4mdec->info.finfo->n_planes,
          y4mdec->info.offset, y4mdec->info.stride);
    } else if (memcmp (&y4mdec->info, &y4mdec->out_info,
            sizeof (y4mdec->info)) != 0) {
      GstBuffer *outbuf;
      GstVideoFrame iframe, oframe;
      gint i, j;
      gint w, h, istride, ostride;
      guint8 *src, *dest;

      /* Allocate a new buffer and do stride conversion */
      g_assert (y4mdec->pool != NULL);

      flow_ret = gst_buffer_pool_acquire_buffer (y4mdec->pool, &outbuf, NULL);
      if (flow_ret != GST_FLOW_OK) {
        gst_buffer_unref (buffer);
        break;
      }

      gst_video_frame_map (&iframe, &y4mdec->info, buffer, GST_MAP_READ);
      gst_video_frame_map (&oframe, &y4mdec->out_info, outbuf, GST_MAP_WRITE);

      for (i = 0; i < 3; i++) {
        w = GST_VIDEO_FRAME_COMP_WIDTH (&iframe, i);
        h = GST_VIDEO_FRAME_COMP_HEIGHT (&iframe, i);
        istride = GST_VIDEO_FRAME_COMP_STRIDE (&iframe, i);
        ostride = GST_VIDEO_FRAME_COMP_STRIDE (&oframe, i);
        src = GST_VIDEO_FRAME_COMP_DATA (&iframe, i);
        dest = GST_VIDEO_FRAME_COMP_DATA (&oframe, i);

        for (j = 0; j < h; j++) {
          memcpy (dest, src, w);

          dest += ostride;
          src += istride;
        }
      }

      gst_video_frame_unmap (&iframe);
      gst_video_frame_unmap (&oframe);
      gst_buffer_copy_into (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
      gst_buffer_unref (buffer);
      buffer = outbuf;
    }

    flow_ret = gst_pad_push (y4mdec->srcpad, buffer);
    if (flow_ret != GST_FLOW_OK)
      break;
  }

  GST_DEBUG ("returning %d", flow_ret);

  return flow_ret;
}
/* Copy fixed header and extension. Replace current ssrc by ssrc1,
 * remove OSN and replace current seq num by OSN.
 * Copy memory to avoid to manually copy each rtp buffer field.
 */
static GstBuffer *
_gst_rtp_buffer_new_from_rtx (GstRTPBuffer * rtp, guint32 ssrc1,
    guint16 orign_seqnum, guint8 origin_payload_type)
{
  GstMemory *mem = NULL;
  GstRTPBuffer new_rtp = GST_RTP_BUFFER_INIT;
  GstBuffer *new_buffer = gst_buffer_new ();
  GstMapInfo map;
  guint payload_len = 0;

  /* copy fixed header */
  mem = gst_memory_copy (rtp->map[0].memory,
      (guint8 *) rtp->data[0] - rtp->map[0].data, rtp->size[0]);
  gst_buffer_append_memory (new_buffer, mem);

  /* copy extension if any */
  if (rtp->size[1]) {
    mem = gst_memory_copy (rtp->map[1].memory,
        (guint8 *) rtp->data[1] - rtp->map[1].data, rtp->size[1]);
    gst_buffer_append_memory (new_buffer, mem);
  }

  /* copy payload and remove OSN */
  payload_len = rtp->size[2] - 2;
  mem = gst_allocator_alloc (NULL, payload_len, NULL);

  gst_memory_map (mem, &map, GST_MAP_WRITE);
  if (rtp->size[2])
    memcpy (map.data, (guint8 *) rtp->data[2] + 2, payload_len);
  gst_memory_unmap (mem, &map);
  gst_buffer_append_memory (new_buffer, mem);

  /* the sender always constructs rtx packets without padding,
   * But the receiver can still receive rtx packets with padding.
   * So just copy it.
   */
  if (rtp->size[3]) {
    guint pad_len = rtp->size[3];

    mem = gst_allocator_alloc (NULL, pad_len, NULL);

    gst_memory_map (mem, &map, GST_MAP_WRITE);
    map.data[pad_len - 1] = pad_len;
    gst_memory_unmap (mem, &map);

    gst_buffer_append_memory (new_buffer, mem);
  }

  /* set ssrc and seq num */
  gst_rtp_buffer_map (new_buffer, GST_MAP_WRITE, &new_rtp);
  gst_rtp_buffer_set_ssrc (&new_rtp, ssrc1);
  gst_rtp_buffer_set_seq (&new_rtp, orign_seqnum);
  gst_rtp_buffer_set_payload_type (&new_rtp, origin_payload_type);
  gst_rtp_buffer_unmap (&new_rtp);

  gst_buffer_copy_into (new_buffer, rtp->buffer,
      GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
  GST_BUFFER_FLAG_SET (new_buffer, GST_RTP_BUFFER_FLAG_RETRANSMISSION);

  return new_buffer;
}
/**
 * gst_vaapi_plugin_base_get_input_buffer:
 * @plugin: a #GstVaapiPluginBase
 * @incaps: the sink pad (input) buffer
 * @outbuf_ptr: the pointer to location to the VA surface backed buffer
 *
 * Acquires the sink pad (input) buffer as a VA surface backed
 * buffer. This is mostly useful for raw YUV buffers, as source
 * buffers that are already backed as a VA surface are passed
 * verbatim.
 *
 * Returns: #GST_FLOW_OK if the buffer could be acquired
 */
GstFlowReturn
gst_vaapi_plugin_base_get_input_buffer (GstVaapiPluginBase * plugin,
    GstBuffer * inbuf, GstBuffer ** outbuf_ptr)
{
  GstVaapiVideoMeta *meta;
  GstBuffer *outbuf;
  GstVideoFrame src_frame, out_frame;
  gboolean success;

  g_return_val_if_fail (inbuf != NULL, GST_FLOW_ERROR);
  g_return_val_if_fail (outbuf_ptr != NULL, GST_FLOW_ERROR);

  meta = gst_buffer_get_vaapi_video_meta (inbuf);
  if (meta) {
    *outbuf_ptr = gst_buffer_ref (inbuf);
    return GST_FLOW_OK;
  }

  if (!plugin->sinkpad_caps_is_raw)
    goto error_invalid_buffer;

  if (!plugin->sinkpad_buffer_pool)
    goto error_no_pool;

  if (!gst_buffer_pool_set_active (plugin->sinkpad_buffer_pool, TRUE))
    goto error_active_pool;

  outbuf = NULL;
  if (gst_buffer_pool_acquire_buffer (plugin->sinkpad_buffer_pool,
          &outbuf, NULL) != GST_FLOW_OK)
    goto error_create_buffer;

  if (is_dma_buffer (inbuf)) {
    if (!plugin_bind_dma_to_vaapi_buffer (plugin, inbuf, outbuf))
      goto error_bind_dma_buffer;
    goto done;
  }

  if (!gst_video_frame_map (&src_frame, &plugin->sinkpad_info, inbuf,
          GST_MAP_READ))
    goto error_map_src_buffer;

  if (!gst_video_frame_map (&out_frame, &plugin->sinkpad_info, outbuf,
          GST_MAP_WRITE))
    goto error_map_dst_buffer;

  success = gst_video_frame_copy (&out_frame, &src_frame);
  gst_video_frame_unmap (&out_frame);
  gst_video_frame_unmap (&src_frame);
  if (!success)
    goto error_copy_buffer;

done:
  gst_buffer_copy_into (outbuf, inbuf, GST_BUFFER_COPY_FLAGS |
      GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
  *outbuf_ptr = outbuf;
  return GST_FLOW_OK;

  /* ERRORS */
error_no_pool:
  {
    GST_ELEMENT_ERROR (plugin, STREAM, FAILED,
        ("no buffer pool was negotiated"), ("no buffer pool was negotiated"));
    return GST_FLOW_ERROR;
  }
error_active_pool:
  {
    GST_ELEMENT_ERROR (plugin, STREAM, FAILED,
        ("failed to activate buffer pool"), ("failed to activate buffer pool"));
    return GST_FLOW_ERROR;
  }
error_map_dst_buffer:
  {
    gst_video_frame_unmap (&src_frame);
    // fall-through
  }
error_map_src_buffer:
  {
    GST_WARNING ("failed to map buffer");
    gst_buffer_unref (outbuf);
    return GST_FLOW_NOT_SUPPORTED;
  }

  /* ERRORS */
error_invalid_buffer:
  {
    GST_ELEMENT_ERROR (plugin, STREAM, FAILED,
        ("failed to validate source buffer"),
        ("failed to validate source buffer"));
    return GST_FLOW_ERROR;
  }
error_create_buffer:
  {
    GST_ELEMENT_ERROR (plugin, STREAM, FAILED, ("Allocation failed"),
        ("failed to create buffer"));
    return GST_FLOW_ERROR;
  }
error_bind_dma_buffer:
  {
    GST_ELEMENT_ERROR (plugin, STREAM, FAILED, ("Allocation failed"),
        ("failed to bind dma_buf to VA surface buffer"));
    gst_buffer_unref (outbuf);
    return GST_FLOW_ERROR;
  }
error_copy_buffer:
  {
    GST_WARNING ("failed to upload buffer to VA surface");
    gst_buffer_unref (outbuf);
    return GST_FLOW_NOT_SUPPORTED;
  }
}
Пример #23
0
static GstFlowReturn
gst_mfxpostproc_transform (GstBaseTransform * trans, GstBuffer * inbuf,
    GstBuffer * outbuf)
{
  GstMfxPostproc *const vpp = GST_MFXPOSTPROC (trans);
  GstMfxVideoMeta *inbuf_meta, *outbuf_meta;
  GstMfxSurface *surface, *out_surface;
  GstMfxFilterStatus status = GST_MFX_FILTER_STATUS_SUCCESS;
  GstFlowReturn ret = GST_FLOW_OK;
  GstBuffer *buf = NULL;
  GstMfxRectangle *crop_rect = NULL;
  GstClockTime timestamp;

  timestamp = GST_BUFFER_TIMESTAMP (inbuf);

  ret = gst_mfx_plugin_base_get_input_buffer (GST_MFX_PLUGIN_BASE (vpp),
          inbuf, &buf);
  if (GST_FLOW_OK != ret)
    return ret;

  inbuf_meta = gst_buffer_get_mfx_video_meta (buf);
  surface = gst_mfx_video_meta_get_surface (inbuf_meta);
  if (!surface)
    goto error_create_surface;

  do {
    if (vpp->flags & GST_MFX_POSTPROC_FLAG_FRC) {
      if (GST_MFX_FILTER_STATUS_ERROR_MORE_SURFACE != status)
        gst_buffer_replace (&buf, NULL);
      buf = create_output_buffer (vpp);
      if (!buf)
        goto error_create_buffer;
    }

    status = gst_mfx_filter_process (vpp->filter, surface, &out_surface);
    if (GST_MFX_FILTER_STATUS_SUCCESS != status
        && GST_MFX_FILTER_STATUS_ERROR_MORE_SURFACE != status
        && GST_MFX_FILTER_STATUS_ERROR_MORE_DATA != status)
      goto error_process_vpp;

    if (GST_MFX_FILTER_STATUS_ERROR_MORE_SURFACE == status)
      outbuf_meta = gst_buffer_get_mfx_video_meta (buf);
    else
      outbuf_meta = gst_buffer_get_mfx_video_meta (outbuf);

    if (!outbuf_meta)
      goto error_create_meta;

    gst_mfx_video_meta_set_surface (outbuf_meta, out_surface);
    crop_rect = gst_mfx_surface_get_crop_rect (out_surface);
    if (crop_rect) {
      GstVideoCropMeta *const crop_meta =
          gst_buffer_add_video_crop_meta (outbuf);
      if (crop_meta) {
        crop_meta->x = crop_rect->x;
        crop_meta->y = crop_rect->y;
        crop_meta->width = crop_rect->width;
        crop_meta->height = crop_rect->height;
      }
    }

    if (GST_MFX_FILTER_STATUS_ERROR_MORE_DATA == status) {
      gst_buffer_unref (buf);
      return GST_BASE_TRANSFORM_FLOW_DROPPED;
    }

    if (GST_MFX_FILTER_STATUS_ERROR_MORE_SURFACE == status) {
      GST_BUFFER_TIMESTAMP (buf) = timestamp;
      GST_BUFFER_DURATION (buf) = vpp->field_duration;
      timestamp += vpp->field_duration;
      ret = gst_pad_push (trans->srcpad, buf);
    }
    else {
      if (vpp->flags & GST_MFX_POSTPROC_FLAG_FRC) {
        GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
        GST_BUFFER_DURATION (outbuf) = vpp->field_duration;
      }
      else {
        gst_buffer_copy_into (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
      }
    }
  } while (GST_MFX_FILTER_STATUS_ERROR_MORE_SURFACE == status
           && GST_FLOW_OK == ret);

  gst_mfx_surface_dequeue(surface);

#if GST_CHECK_VERSION(1,8,0)
  gst_mfx_plugin_base_export_dma_buffer (GST_MFX_PLUGIN_BASE (vpp), outbuf);
#endif // GST_CHECK_VERSION

  gst_buffer_unref (buf);
  return ret;
  /* ERRORS */
error_create_buffer:
  {
    GST_ERROR ("failed to output buffer");
    gst_buffer_unref (buf);
    return GST_FLOW_ERROR;
  }
error_create_meta:
  {
    GST_ERROR ("failed to create new output buffer meta");
    gst_buffer_unref (buf);
    return GST_FLOW_ERROR;
  }
error_create_surface:
  {
    GST_ERROR ("failed to create surface surface from buffer");
    gst_buffer_unref (buf);
    return GST_FLOW_ERROR;
  }
error_process_vpp:
  {
    GST_ERROR ("failed to apply VPP (error %d)", status);
    gst_buffer_unref (buf);
    return GST_FLOW_ERROR;
  }
}
Пример #24
0
static GstFlowReturn
stereosplit_chain (GstPad * pad, GstGLStereoSplit * split, GstBuffer * buf)
{
  GstBuffer *uploaded_buffer, *converted_buffer, *left, *right;
  GstBuffer *split_buffer = NULL;
  GstFlowReturn ret;
  gint i, n_planes;

  if (!split->upload)
    _init_upload (split);

  n_planes = GST_VIDEO_INFO_N_PLANES (&split->viewconvert->out_info);

  GST_LOG_OBJECT (split, "chaining buffer %" GST_PTR_FORMAT, buf);

  if (GST_GL_UPLOAD_DONE != gst_gl_upload_perform_with_buffer (split->upload,
          buf, &uploaded_buffer)) {
    gst_buffer_unref (buf);
    GST_ELEMENT_ERROR (split, RESOURCE, NOT_FOUND, ("%s",
            "Failed to upload buffer"), (NULL));
    return GST_FLOW_ERROR;
  }
  gst_buffer_unref (buf);

  if (!(converted_buffer =
          gst_gl_color_convert_perform (split->convert, uploaded_buffer))) {
    GST_ELEMENT_ERROR (split, RESOURCE, NOT_FOUND, ("%s",
            "Failed to convert buffer"), (NULL));
    gst_buffer_unref (uploaded_buffer);
    return GST_FLOW_ERROR;
  }
  gst_buffer_unref (uploaded_buffer);

  if (gst_gl_view_convert_submit_input_buffer (split->viewconvert,
          GST_BUFFER_IS_DISCONT (converted_buffer),
          converted_buffer) != GST_FLOW_OK) {
    GST_ELEMENT_ERROR (split, RESOURCE, NOT_FOUND, ("%s",
            "Failed to 3d convert buffer"),
        ("Could not get submit input buffer"));
    return GST_FLOW_ERROR;
  }

  ret = gst_gl_view_convert_get_output (split->viewconvert, &split_buffer);
  if (ret != GST_FLOW_OK) {
    GST_ELEMENT_ERROR (split, RESOURCE, NOT_FOUND, ("%s",
            "Failed to 3d convert buffer"), ("Could not get output buffer"));
    return GST_FLOW_ERROR;
  }
  if (split_buffer == NULL)
    return GST_FLOW_OK;         /* Need another input buffer */

  left = gst_buffer_new ();
  gst_buffer_copy_into (left, buf,
      GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
  GST_BUFFER_FLAG_UNSET (left, GST_VIDEO_BUFFER_FLAG_FIRST_IN_BUNDLE);

  gst_buffer_add_parent_buffer_meta (left, split_buffer);

  for (i = 0; i < n_planes; i++) {
    GstMemory *mem = gst_buffer_get_memory (split_buffer, i);
    gst_buffer_append_memory (left, mem);
  }

  ret = gst_pad_push (split->left_pad, gst_buffer_ref (left));
  /* Allow unlinked on the first pad - as long as the 2nd isn't unlinked */
  gst_buffer_unref (left);
  if (G_UNLIKELY (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)) {
    gst_buffer_unref (split_buffer);
    return ret;
  }

  right = gst_buffer_new ();
  gst_buffer_copy_into (right, buf,
      GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
  GST_BUFFER_FLAG_UNSET (left, GST_VIDEO_BUFFER_FLAG_FIRST_IN_BUNDLE);
  gst_buffer_add_parent_buffer_meta (right, split_buffer);
  for (i = n_planes; i < n_planes * 2; i++) {
    GstMemory *mem = gst_buffer_get_memory (split_buffer, i);
    gst_buffer_append_memory (right, mem);
  }

  ret = gst_pad_push (split->right_pad, gst_buffer_ref (right));
  gst_buffer_unref (right);
  gst_buffer_unref (split_buffer);
  return ret;
}
Пример #25
0
static GstFlowReturn
gst_frei0r_mixer_collected (GstCollectPads * pads, GstFrei0rMixer * self)
{
  GstBuffer *inbuf0 = NULL, *inbuf1 = NULL, *inbuf2 = NULL;
  GstBuffer *outbuf = NULL;
  GstFlowReturn ret = GST_FLOW_OK;
  GSList *l;
  GstFrei0rMixerClass *klass = GST_FREI0R_MIXER_GET_CLASS (self);
  GstClockTime timestamp;
  gdouble time;
  GstSegment *segment = NULL;
  GstAllocationParams alloc_params = { 0, 31, 0, 0 };
  GstMapInfo outmap, inmap0, inmap1, inmap2;

  if (G_UNLIKELY (self->info.width <= 0 || self->info.height <= 0))
    return GST_FLOW_NOT_NEGOTIATED;

  if (G_UNLIKELY (!self->f0r_instance)) {
    self->f0r_instance = gst_frei0r_instance_construct (klass->ftable,
        klass->properties, klass->n_properties, self->property_cache,
        self->info.width, self->info.height);
    if (G_UNLIKELY (!self->f0r_instance))
      return GST_FLOW_ERROR;
  }

  if (self->segment_event) {
    gst_pad_push_event (self->src, self->segment_event);
    self->segment_event = NULL;
  }

  /* FIXME Request an allocator and/or pool */
  outbuf = gst_buffer_new_allocate (NULL, self->info.size, &alloc_params);

  for (l = pads->data; l; l = l->next) {
    GstCollectData *cdata = l->data;

    if (cdata->pad == self->sink0) {
      inbuf0 = gst_collect_pads_pop (pads, cdata);
      segment = &cdata->segment;
    } else if (cdata->pad == self->sink1) {
      inbuf1 = gst_collect_pads_pop (pads, cdata);
    } else if (cdata->pad == self->sink2) {
      inbuf2 = gst_collect_pads_pop (pads, cdata);
    }
  }

  if (!inbuf0 || !inbuf1 || (!inbuf2 && self->sink2))
    goto eos;

  gst_buffer_map (outbuf, &outmap, GST_MAP_READWRITE);
  gst_buffer_map (inbuf0, &inmap0, GST_MAP_READ);
  gst_buffer_map (inbuf1, &inmap1, GST_MAP_READ);
  if (inbuf2)
    gst_buffer_map (inbuf2, &inmap2, GST_MAP_READ);

  g_assert (segment != NULL);
  timestamp = GST_BUFFER_PTS (inbuf0);
  timestamp = gst_segment_to_stream_time (segment, GST_FORMAT_TIME, timestamp);

  GST_DEBUG_OBJECT (self, "sync to %" GST_TIME_FORMAT,
      GST_TIME_ARGS (timestamp));

  if (GST_CLOCK_TIME_IS_VALID (timestamp))
    gst_object_sync_values (GST_OBJECT (self), timestamp);

  gst_buffer_copy_into (outbuf, inbuf0,
      GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
  time = ((gdouble) GST_BUFFER_PTS (outbuf)) / GST_SECOND;

  GST_OBJECT_LOCK (self);
  klass->ftable->update2 (self->f0r_instance, time,
      (const guint32 *) inmap0.data, (const guint32 *) inmap1.data,
      (inbuf2) ? (const guint32 *) inmap2.data : NULL, (guint32 *) outmap.data);
  GST_OBJECT_UNLOCK (self);

  gst_buffer_unmap (outbuf, &outmap);
  gst_buffer_unref (inbuf0);
  gst_buffer_unmap (inbuf0, &inmap0);
  gst_buffer_unref (inbuf1);
  gst_buffer_unmap (inbuf1, &inmap1);
  if (inbuf2) {
    gst_buffer_unmap (inbuf2, &inmap2);
    gst_buffer_unref (inbuf2);
  }

  ret = gst_pad_push (self->src, outbuf);

  return ret;

eos:
  {
    GST_DEBUG_OBJECT (self, "no data available, must be EOS");
    gst_buffer_unref (outbuf);

    if (inbuf0)
      gst_buffer_unref (inbuf0);
    if (inbuf1)
      gst_buffer_unref (inbuf1);
    if (inbuf2)
      gst_buffer_unref (inbuf2);

    gst_pad_push_event (self->src, gst_event_new_eos ());
    return GST_FLOW_EOS;
  }
}
Пример #26
0
static GstFlowReturn
gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
    GstVideoCodecFrame * frame)
{
  GstV4l2Error error = GST_V4L2_ERROR_INIT;
  GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
  GstFlowReturn ret = GST_FLOW_OK;
  gboolean processed = FALSE;
  GstBuffer *tmp;

  GST_DEBUG_OBJECT (self, "Handling frame %d", frame->system_frame_number);

  if (G_UNLIKELY (!g_atomic_int_get (&self->active)))
    goto flushing;

  if (G_UNLIKELY (!GST_V4L2_IS_ACTIVE (self->v4l2output))) {
    if (!self->input_state)
      goto not_negotiated;
    if (!gst_v4l2_object_set_format (self->v4l2output, self->input_state->caps,
          &error))
      goto not_negotiated;
  }

  if (G_UNLIKELY (!GST_V4L2_IS_ACTIVE (self->v4l2capture))) {
    GstBufferPool *pool = GST_BUFFER_POOL (self->v4l2output->pool);
    GstVideoInfo info;
    GstVideoCodecState *output_state;
    GstBuffer *codec_data;
    GstCaps *acquired_caps, *available_caps, *caps, *filter;
    GstStructure *st;

    GST_DEBUG_OBJECT (self, "Sending header");

    codec_data = self->input_state->codec_data;

    /* We are running in byte-stream mode, so we don't know the headers, but
     * we need to send something, otherwise the decoder will refuse to
     * intialize.
     */
    if (codec_data) {
      gst_buffer_ref (codec_data);
    } else {
      codec_data = gst_buffer_ref (frame->input_buffer);
      processed = TRUE;
    }

    /* Ensure input internal pool is active */
    if (!gst_buffer_pool_is_active (pool)) {
      GstStructure *config = gst_buffer_pool_get_config (pool);
      gst_buffer_pool_config_set_params (config, self->input_state->caps,
          self->v4l2output->info.size, 2, 2);

      /* There is no reason to refuse this config */
      if (!gst_buffer_pool_set_config (pool, config))
        goto activate_failed;

      if (!gst_buffer_pool_set_active (pool, TRUE))
        goto activate_failed;
    }

    GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
    ret =
        gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->
            v4l2output->pool), &codec_data);
    GST_VIDEO_DECODER_STREAM_LOCK (decoder);

    gst_buffer_unref (codec_data);

    /* For decoders G_FMT returns coded size, G_SELECTION returns visible size
     * in the compose rectangle. gst_v4l2_object_acquire_format() checks both
     * and returns the visible size as with/height and the coded size as
     * padding. */
    if (!gst_v4l2_object_acquire_format (self->v4l2capture, &info))
      goto not_negotiated;

    /* Create caps from the acquired format, remove the format field */
    acquired_caps = gst_video_info_to_caps (&info);
    st = gst_caps_get_structure (acquired_caps, 0);
    gst_structure_remove_field (st, "format");

    /* Probe currently available pixel formats */
    available_caps = gst_v4l2_object_probe_caps (self->v4l2capture, NULL);
    available_caps = gst_caps_make_writable (available_caps);

    /* Replace coded size with visible size, we want to negotiate visible size
     * with downstream, not coded size. */
    gst_caps_map_in_place (available_caps, gst_v4l2_video_remove_padding, self);

    filter = gst_caps_intersect_full (available_caps, acquired_caps,
        GST_CAPS_INTERSECT_FIRST);
    gst_caps_unref (acquired_caps);
    gst_caps_unref (available_caps);
    caps = gst_pad_peer_query_caps (decoder->srcpad, filter);
    gst_caps_unref (filter);

    GST_DEBUG_OBJECT (self, "Possible decoded caps: %" GST_PTR_FORMAT, caps);
    if (gst_caps_is_empty (caps)) {
      gst_caps_unref (caps);
      goto not_negotiated;
    }

    /* Fixate pixel format */
    caps = gst_caps_fixate (caps);

    GST_DEBUG_OBJECT (self, "Chosen decoded caps: %" GST_PTR_FORMAT, caps);

    /* Try to set negotiated format, on success replace acquired format */
    if (gst_v4l2_object_set_format (self->v4l2capture, caps, &error))
      gst_video_info_from_caps (&info, caps);
    else
      gst_v4l2_clear_error (&error);
    gst_caps_unref (caps);

    output_state = gst_video_decoder_set_output_state (decoder,
        info.finfo->format, info.width, info.height, self->input_state);

    /* Copy the rest of the information, there might be more in the future */
    output_state->info.interlace_mode = info.interlace_mode;
    gst_video_codec_state_unref (output_state);

    if (!gst_video_decoder_negotiate (decoder)) {
      if (GST_PAD_IS_FLUSHING (decoder->srcpad))
        goto flushing;
      else
        goto not_negotiated;
    }

    /* Ensure our internal pool is activated */
    if (!gst_buffer_pool_set_active (GST_BUFFER_POOL (self->v4l2capture->pool),
            TRUE))
      goto activate_failed;
  }

  if (g_atomic_int_get (&self->processing) == FALSE) {
    /* It's possible that the processing thread stopped due to an error */
    if (self->output_flow != GST_FLOW_OK &&
        self->output_flow != GST_FLOW_FLUSHING) {
      GST_DEBUG_OBJECT (self, "Processing loop stopped with error, leaving");
      ret = self->output_flow;
      goto drop;
    }

    GST_DEBUG_OBJECT (self, "Starting decoding thread");

    /* Start the processing task, when it quits, the task will disable input
     * processing to unlock input if draining, or prevent potential block */
    g_atomic_int_set (&self->processing, TRUE);
    if (!gst_pad_start_task (decoder->srcpad,
            (GstTaskFunction) gst_v4l2_video_dec_loop, self,
            (GDestroyNotify) gst_v4l2_video_dec_loop_stopped))
      goto start_task_failed;
  }

  if (!processed) {
    GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
    ret =
        gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->v4l2output->
            pool), &frame->input_buffer);
    GST_VIDEO_DECODER_STREAM_LOCK (decoder);

    if (ret == GST_FLOW_FLUSHING) {
      if (g_atomic_int_get (&self->processing) == FALSE)
        ret = self->output_flow;
      goto drop;
    } else if (ret != GST_FLOW_OK) {
      goto process_failed;
    }
  }

  /* No need to keep input arround */
  tmp = frame->input_buffer;
  frame->input_buffer = gst_buffer_new ();
  gst_buffer_copy_into (frame->input_buffer, tmp,
      GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS |
      GST_BUFFER_COPY_META, 0, 0);
  gst_buffer_unref (tmp);

  gst_video_codec_frame_unref (frame);
  return ret;

  /* ERRORS */
not_negotiated:
  {
    GST_ERROR_OBJECT (self, "not negotiated");
    ret = GST_FLOW_NOT_NEGOTIATED;
    gst_v4l2_error (self, &error);
    goto drop;
  }
activate_failed:
  {
    GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
        (_("Failed to allocate required memory.")),
        ("Buffer pool activation failed"));
    ret = GST_FLOW_ERROR;
    goto drop;
  }
flushing:
  {
    ret = GST_FLOW_FLUSHING;
    goto drop;
  }

start_task_failed:
  {
    GST_ELEMENT_ERROR (self, RESOURCE, FAILED,
        (_("Failed to start decoding thread.")), (NULL));
    g_atomic_int_set (&self->processing, FALSE);
    ret = GST_FLOW_ERROR;
    goto drop;
  }
process_failed:
  {
    GST_ELEMENT_ERROR (self, RESOURCE, FAILED,
        (_("Failed to process frame.")),
        ("Maybe be due to not enough memory or failing driver"));
    ret = GST_FLOW_ERROR;
    goto drop;
  }
drop:
  {
    gst_video_decoder_drop_frame (decoder, frame);
    return ret;
  }
}
Пример #27
0
static GstFlowReturn
gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
  GstShmSink *self = GST_SHM_SINK (bsink);
  int rv = 0;
  GstMapInfo map;
  gboolean need_new_memory = FALSE;
  GstFlowReturn ret = GST_FLOW_OK;
  GstMemory *memory = NULL;
  GstBuffer *sendbuf = NULL;
  gsize written_bytes;

  GST_OBJECT_LOCK (self);
  while (self->wait_for_connection && !self->clients) {
    g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self));
    if (self->unlock) {
      GST_OBJECT_UNLOCK (self);
      ret = gst_base_sink_wait_preroll (bsink);
      if (ret == GST_FLOW_OK)
        GST_OBJECT_LOCK (self);
      else
        return ret;
    }
  }

  while (!gst_shm_sink_can_render (self, GST_BUFFER_TIMESTAMP (buf))) {
    g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self));
    if (self->unlock) {
      GST_OBJECT_UNLOCK (self);
      ret = gst_base_sink_wait_preroll (bsink);
      if (ret == GST_FLOW_OK)
        GST_OBJECT_LOCK (self);
      else
        return ret;
    }
  }


  if (gst_buffer_n_memory (buf) > 1) {
    GST_LOG_OBJECT (self, "Buffer %p has %d GstMemory, we only support a single"
        " one, need to do a memcpy", buf, gst_buffer_n_memory (buf));
    need_new_memory = TRUE;
  } else {
    memory = gst_buffer_peek_memory (buf, 0);

    if (memory->allocator != GST_ALLOCATOR (self->allocator)) {
      need_new_memory = TRUE;
      GST_LOG_OBJECT (self, "Memory in buffer %p was not allocated by "
          "%" GST_PTR_FORMAT ", will memcpy", buf, memory->allocator);
    }
  }

  if (need_new_memory) {
    if (gst_buffer_get_size (buf) > sp_writer_get_max_buf_size (self->pipe)) {
      gsize area_size = sp_writer_get_max_buf_size (self->pipe);
      GST_ELEMENT_ERROR (self, RESOURCE, NO_SPACE_LEFT, (NULL),
          ("Shared memory area of size %" G_GSIZE_FORMAT " is smaller than"
              "buffer of size %" G_GSIZE_FORMAT, area_size,
              gst_buffer_get_size (buf)));
      goto error;
    }

    while ((memory =
            gst_shm_sink_allocator_alloc_locked (self->allocator,
                gst_buffer_get_size (buf), &self->params)) == NULL) {
      g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self));
      if (self->unlock) {
        GST_OBJECT_UNLOCK (self);
        ret = gst_base_sink_wait_preroll (bsink);
        if (ret == GST_FLOW_OK)
          GST_OBJECT_LOCK (self);
        else
          return ret;
      }
    }

    while (self->wait_for_connection && !self->clients) {
      g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self));
      if (self->unlock) {
        GST_OBJECT_UNLOCK (self);
        ret = gst_base_sink_wait_preroll (bsink);
        if (ret == GST_FLOW_OK) {
          GST_OBJECT_LOCK (self);
        } else {
          gst_memory_unref (memory);
          return ret;
        }
      }
    }

    if (!gst_memory_map (memory, &map, GST_MAP_WRITE)) {
      GST_ELEMENT_ERROR (self, STREAM, FAILED,
          (NULL), ("Failed to map memory"));
      goto error;
    }

    GST_DEBUG_OBJECT (self,
        "Copying %" G_GSIZE_FORMAT " bytes into map of size %" G_GSIZE_FORMAT
        " bytes.", gst_buffer_get_size (buf), map.size);
    written_bytes = gst_buffer_extract (buf, 0, map.data, map.size);
    GST_DEBUG_OBJECT (self, "Copied %" G_GSIZE_FORMAT " bytes.", written_bytes);
    gst_memory_unmap (memory, &map);

    sendbuf = gst_buffer_new ();
    if (!gst_buffer_copy_into (sendbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1)) {
      GST_ELEMENT_ERROR (self, STREAM, FAILED,
          (NULL), ("Failed to copy data into send buffer"));
      gst_buffer_unref (sendbuf);
      goto error;
    }
    gst_buffer_append_memory (sendbuf, memory);
  } else {
    sendbuf = gst_buffer_ref (buf);
  }

  if (!gst_buffer_map (sendbuf, &map, GST_MAP_READ)) {
    GST_ELEMENT_ERROR (self, STREAM, FAILED,
        (NULL), ("Failed to map data into send buffer"));
    goto error;
  }

  /* Make the memory readonly as of now as we've sent it to the other side
   * We know it's not mapped for writing anywhere as we just mapped it for
   * reading
   */
  rv = sp_writer_send_buf (self->pipe, (char *) map.data, map.size, sendbuf);
  if (rv == -1) {
    GST_ELEMENT_ERROR (self, STREAM, FAILED,
        (NULL), ("Failed to send data over SHM"));
    gst_buffer_unmap (sendbuf, &map);
    goto error;
  }

  gst_buffer_unmap (sendbuf, &map);

  GST_OBJECT_UNLOCK (self);

  if (rv == 0) {
    GST_DEBUG_OBJECT (self, "No clients connected, unreffing buffer");
    gst_buffer_unref (sendbuf);
  }

  return ret;

error:
  GST_OBJECT_UNLOCK (self);
  return GST_FLOW_ERROR;
}
Пример #28
0
static GstFlowReturn
gst_deinterleave_process (GstDeinterleave * self, GstBuffer * buf)
{
  GstFlowReturn ret = GST_FLOW_OK;
  guint channels = GST_AUDIO_INFO_CHANNELS (&self->audio_info);
  guint pads_pushed = 0, buffers_allocated = 0;
  guint nframes =
      gst_buffer_get_size (buf) / channels /
      (GST_AUDIO_INFO_WIDTH (&self->audio_info) / 8);
  guint bufsize = nframes * (GST_AUDIO_INFO_WIDTH (&self->audio_info) / 8);
  guint i;
  GList *srcs;
  GstBuffer **buffers_out = g_new0 (GstBuffer *, channels);
  guint8 *in, *out;
  GstMapInfo read_info;
  GList *pending_events, *l;

  /* Send any pending events to all src pads */
  GST_OBJECT_LOCK (self);
  pending_events = self->pending_events;
  self->pending_events = NULL;
  GST_OBJECT_UNLOCK (self);

  if (pending_events) {
    GstEvent *event;

    GST_DEBUG_OBJECT (self, "Sending pending events to all src pads");
    for (l = pending_events; l; l = l->next) {
      event = l->data;
      for (srcs = self->srcpads; srcs != NULL; srcs = srcs->next)
        gst_pad_push_event (GST_PAD (srcs->data), gst_event_ref (event));
      gst_event_unref (event);
    }
    g_list_free (pending_events);
  }

  gst_buffer_map (buf, &read_info, GST_MAP_READ);

  /* Allocate buffers */
  for (srcs = self->srcpads, i = 0; srcs; srcs = srcs->next, i++) {
    buffers_out[i] = gst_buffer_new_allocate (NULL, bufsize, NULL);

    /* Make sure we got a correct buffer. The only other case we allow
     * here is an unliked pad */
    if (!buffers_out[i])
      goto alloc_buffer_failed;
    else if (buffers_out[i] && gst_buffer_get_size (buffers_out[i]) != bufsize)
      goto alloc_buffer_bad_size;

    if (buffers_out[i]) {
      gst_buffer_copy_into (buffers_out[i], buf, GST_BUFFER_COPY_METADATA, 0,
          -1);
      buffers_allocated++;
    }
  }

  /* Return NOT_LINKED if no pad was linked */
  if (!buffers_allocated) {
    GST_WARNING_OBJECT (self,
        "Couldn't allocate any buffers because no pad was linked");
    ret = GST_FLOW_NOT_LINKED;
    goto done;
  }

  /* deinterleave */
  for (srcs = self->srcpads, i = 0; srcs; srcs = srcs->next, i++) {
    GstPad *pad = (GstPad *) srcs->data;
    GstMapInfo write_info;

    in = (guint8 *) read_info.data;
    in += i * (GST_AUDIO_INFO_WIDTH (&self->audio_info) / 8);
    if (buffers_out[i]) {
      gst_buffer_map (buffers_out[i], &write_info, GST_MAP_WRITE);
      out = (guint8 *) write_info.data;
      self->func (out, in, channels, nframes);
      gst_buffer_unmap (buffers_out[i], &write_info);

      ret = gst_pad_push (pad, buffers_out[i]);
      buffers_out[i] = NULL;
      if (ret == GST_FLOW_OK)
        pads_pushed++;
      else if (ret == GST_FLOW_NOT_LINKED)
        ret = GST_FLOW_OK;
      else
        goto push_failed;
    }
  }

  /* Return NOT_LINKED if no pad was linked */
  if (!pads_pushed)
    ret = GST_FLOW_NOT_LINKED;

  GST_DEBUG_OBJECT (self, "Pushed on %d pads", pads_pushed);

done:
  gst_buffer_unmap (buf, &read_info);
  gst_buffer_unref (buf);
  g_free (buffers_out);
  return ret;

alloc_buffer_failed:
  {
    GST_WARNING ("gst_pad_alloc_buffer() returned %s", gst_flow_get_name (ret));
    goto clean_buffers;

  }
alloc_buffer_bad_size:
  {
    GST_WARNING ("called alloc_buffer(), but didn't get requested bytes");
    ret = GST_FLOW_NOT_NEGOTIATED;
    goto clean_buffers;
  }
push_failed:
  {
    GST_DEBUG ("push() failed, flow = %s", gst_flow_get_name (ret));
    goto clean_buffers;
  }
clean_buffers:
  {
    gst_buffer_unmap (buf, &read_info);
    for (i = 0; i < channels; i++) {
      if (buffers_out[i])
        gst_buffer_unref (buffers_out[i]);
    }
    gst_buffer_unref (buf);
    g_free (buffers_out);
    return ret;
  }
}
Пример #29
0
static GstFlowReturn
gst_shape_wipe_video_sink_chain (GstPad * pad, GstObject * parent,
    GstBuffer * buffer)
{
  GstShapeWipe *self = GST_SHAPE_WIPE (parent);
  GstFlowReturn ret = GST_FLOW_OK;
  GstBuffer *mask = NULL, *outbuf = NULL;
  GstClockTime timestamp;
  gboolean new_outbuf = FALSE;
  GstVideoFrame inframe, outframe, maskframe;

  if (G_UNLIKELY (GST_VIDEO_INFO_FORMAT (&self->vinfo) ==
          GST_VIDEO_FORMAT_UNKNOWN))
    goto not_negotiated;

  timestamp = GST_BUFFER_TIMESTAMP (buffer);
  timestamp =
      gst_segment_to_stream_time (&self->segment, GST_FORMAT_TIME, timestamp);

  if (GST_CLOCK_TIME_IS_VALID (timestamp))
    gst_object_sync_values (GST_OBJECT (self), timestamp);

  GST_LOG_OBJECT (self,
      "Blending buffer with timestamp %" GST_TIME_FORMAT " at position %f",
      GST_TIME_ARGS (timestamp), self->mask_position);

  g_mutex_lock (&self->mask_mutex);
  if (self->shutdown)
    goto shutdown;

  if (!self->mask)
    g_cond_wait (&self->mask_cond, &self->mask_mutex);

  if (self->mask == NULL || self->shutdown) {
    goto shutdown;
  } else {
    mask = gst_buffer_ref (self->mask);
  }
  g_mutex_unlock (&self->mask_mutex);

  if (!gst_shape_wipe_do_qos (self, GST_BUFFER_TIMESTAMP (buffer)))
    goto qos;

  /* Try to blend inplace, if it's not possible
   * get a new buffer from downstream. */
  if (!gst_buffer_is_writable (buffer)) {
    outbuf = gst_buffer_new_allocate (NULL, gst_buffer_get_size (buffer), NULL);
    gst_buffer_copy_into (outbuf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
    new_outbuf = TRUE;
  } else {
    outbuf = buffer;
  }

  gst_video_frame_map (&inframe, &self->vinfo, buffer,
      new_outbuf ? GST_MAP_READ : GST_MAP_READWRITE);
  gst_video_frame_map (&outframe, &self->vinfo, outbuf,
      new_outbuf ? GST_MAP_WRITE : GST_MAP_READWRITE);

  gst_video_frame_map (&maskframe, &self->minfo, mask, GST_MAP_READ);

  switch (GST_VIDEO_INFO_FORMAT (&self->vinfo)) {
    case GST_VIDEO_FORMAT_AYUV:
    case GST_VIDEO_FORMAT_ARGB:
    case GST_VIDEO_FORMAT_ABGR:
      if (self->mask_bpp == 16)
        gst_shape_wipe_blend_argb_16 (self, &inframe, &maskframe, &outframe);
      else
        gst_shape_wipe_blend_argb_8 (self, &inframe, &maskframe, &outframe);
      break;
    case GST_VIDEO_FORMAT_BGRA:
    case GST_VIDEO_FORMAT_RGBA:
      if (self->mask_bpp == 16)
        gst_shape_wipe_blend_bgra_16 (self, &inframe, &maskframe, &outframe);
      else
        gst_shape_wipe_blend_bgra_8 (self, &inframe, &maskframe, &outframe);
      break;
    default:
      g_assert_not_reached ();
      break;
  }

  gst_video_frame_unmap (&outframe);
  gst_video_frame_unmap (&inframe);

  gst_video_frame_unmap (&maskframe);

  gst_buffer_unref (mask);
  if (new_outbuf)
    gst_buffer_unref (buffer);

  ret = gst_pad_push (self->srcpad, outbuf);
  if (G_UNLIKELY (ret != GST_FLOW_OK))
    goto push_failed;

  return ret;

  /* Errors */
not_negotiated:
  {
    GST_ERROR_OBJECT (self, "No valid caps yet");
    gst_buffer_unref (buffer);
    return GST_FLOW_NOT_NEGOTIATED;
  }
shutdown:
  {
    GST_DEBUG_OBJECT (self, "Shutting down");
    gst_buffer_unref (buffer);
    return GST_FLOW_FLUSHING;
  }
qos:
  {
    GST_DEBUG_OBJECT (self, "Dropping buffer because of QoS");
    gst_buffer_unref (buffer);
    gst_buffer_unref (mask);
    return GST_FLOW_OK;
  }
push_failed:
  {
    GST_ERROR_OBJECT (self, "Pushing buffer downstream failed: %s",
        gst_flow_get_name (ret));
    return ret;
  }
}
Пример #30
0
static GstFlowReturn
gst_pnmdec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame)
{
  GstPnmdec *s = (GstPnmdec *) decoder;
  GstMapInfo imap, omap;
  guint i_rowstride;
  guint o_rowstride;
  GstFlowReturn r = GST_FLOW_OK;
  gint bytes, i, total_bytes = 0;

  r = gst_video_decoder_allocate_output_frame (decoder, frame);
  if (r != GST_FLOW_OK) {
    gst_video_decoder_drop_frame (GST_VIDEO_DECODER (s), frame);
    goto out;
  }

  if (s->mngr.info.encoding == GST_PNM_ENCODING_ASCII) {
    /* In case of ASCII parsed data is stored in buf, so input needs to be
       taken from here for frame processing */
    gst_buffer_map (s->buf, &imap, GST_MAP_READ);
  } else {
    gst_buffer_map (frame->input_buffer, &imap, GST_MAP_READ);
  }
  gst_buffer_map (frame->output_buffer, &omap, GST_MAP_WRITE);

  gst_buffer_copy_into (frame->output_buffer, frame->input_buffer,
      GST_BUFFER_COPY_METADATA, 0, 0);

  if (s->mngr.info.type == GST_PNM_TYPE_BITMAP) {
    bytes = (s->mngr.info.width * s->mngr.info.height + 7) / 8;
    for (i = 0; i < bytes; i++) {
      omap.data[i * 8] = (imap.data[i] & 0x80) ? 0 : 255;
      omap.data[i * 8 + 1] = (imap.data[i] & 0x40) ? 0 : 255;
      omap.data[i * 8 + 2] = (imap.data[i] & 0x20) ? 0 : 255;
      omap.data[i * 8 + 3] = (imap.data[i] & 0x10) ? 0 : 255;
      omap.data[i * 8 + 4] = (imap.data[i] & 0x08) ? 0 : 255;
      omap.data[i * 8 + 5] = (imap.data[i] & 0x04) ? 0 : 255;
      omap.data[i * 8 + 6] = (imap.data[i] & 0x02) ? 0 : 255;
      omap.data[i * 8 + 7] = (imap.data[i] & 0x01) ? 0 : 255;
    }
    total_bytes = bytes * 8;
  } else
    /* Need to convert from PNM rowstride to GStreamer rowstride */
  if (s->mngr.info.width % 4 != 0) {
    if (s->mngr.info.type == GST_PNM_TYPE_PIXMAP) {
      i_rowstride = 3 * s->mngr.info.width;
      o_rowstride = GST_ROUND_UP_4 (i_rowstride);
    } else {
      i_rowstride = s->mngr.info.width;
      o_rowstride = GST_ROUND_UP_4 (i_rowstride);
    }

    for (i = 0; i < s->mngr.info.height; i++)
      memcpy (omap.data + i * o_rowstride, imap.data + i * i_rowstride,
          i_rowstride);
    total_bytes = o_rowstride * s->mngr.info.height;
  } else {
    memcpy (omap.data, imap.data, s->size);
    total_bytes = s->size;
  }

  if (s->mngr.info.type != GST_PNM_TYPE_BITMAP) {
    /* Convert the pixels from 0 - max range to 0 - 255 range */
    if (s->mngr.info.max < 255) {
      gint max = s->mngr.info.max;
      for (i = 0; i < total_bytes; i++) {
        if (omap.data[i] <= max) {
          omap.data[i] = 255 * omap.data[i] / max;
        } else {
          /* This is an error case, wherein value in the data stream is
             more than max. Clamp such values to 255 */
          omap.data[i] = 255;
        }
      }
    }
  }

  if (s->mngr.info.encoding == GST_PNM_ENCODING_ASCII) {
    gst_buffer_unmap (s->buf, &imap);
  } else {
    gst_buffer_unmap (frame->input_buffer, &imap);
  }
  gst_buffer_unmap (frame->output_buffer, &omap);

  r = gst_video_decoder_finish_frame (GST_VIDEO_DECODER (s), frame);

out:
  gst_pnmdec_flush (s);

  return r;
}