static gboolean
theora_enc_write_multipass_cache (GstTheoraEnc * enc, gboolean begin,
    gboolean eos)
{
  GError *err = NULL;
  GIOStatus stat = G_IO_STATUS_NORMAL;
  gint bytes_read = 0;
  gsize bytes_written = 0;
  gchar *buf;

  if (begin)
    stat = g_io_channel_seek_position (enc->multipass_cache_fd, 0, G_SEEK_SET,
        &err);
  if (stat != G_IO_STATUS_ERROR) {
    do {
      bytes_read =
          th_encode_ctl (enc->encoder, TH_ENCCTL_2PASS_OUT, &buf, sizeof (buf));
      if (bytes_read > 0)
        g_io_channel_write_chars (enc->multipass_cache_fd, buf, bytes_read,
            &bytes_written, NULL);
    } while (bytes_read > 0 && bytes_written > 0);

  }

  if (stat == G_IO_STATUS_ERROR || bytes_read < 0) {
    if (begin) {
      if (eos)
        GST_ELEMENT_WARNING (enc, RESOURCE, WRITE, (NULL),
            ("Failed to seek to beginning of multipass cache file: %s",
                err->message));
      else
        GST_ELEMENT_ERROR (enc, RESOURCE, WRITE, (NULL),
            ("Failed to seek to beginning of multipass cache file: %s",
                err->message));
    } else {
      GST_ELEMENT_ERROR (enc, RESOURCE, WRITE, (NULL),
          ("Failed to write multipass cache file"));
    }
    if (err)
      g_error_free (err);

    return FALSE;
  }
  return TRUE;
}
static GstBuffer *
gst_rtp_g723_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
{
  GstRtpG723Depay *rtpg723depay;
  GstBuffer *outbuf = NULL;
  gint payload_len;
  gboolean marker;

  rtpg723depay = GST_RTP_G723_DEPAY (depayload);

  payload_len = gst_rtp_buffer_get_payload_len (buf);

  /* At least 4 bytes */
  if (payload_len < 4)
    goto too_small;

  GST_LOG_OBJECT (rtpg723depay, "payload len %d", payload_len);

  outbuf = gst_rtp_buffer_get_payload_buffer (buf);
  marker = gst_rtp_buffer_get_marker (buf);

  if (marker) {
    /* marker bit starts talkspurt */
    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
  }

  GST_LOG_OBJECT (depayload, "pushing buffer of size %d",
      GST_BUFFER_SIZE (outbuf));

  return outbuf;

  /* ERRORS */
too_small:
  {
    GST_ELEMENT_WARNING (rtpg723depay, STREAM, DECODE,
        (NULL), ("G723 RTP payload too small (%d)", payload_len));
    goto bad_packet;
  }
bad_packet:
  {
    /* no fatal error */
    return NULL;
  }
}
GstElement *
gst_play_sink_convert_bin_add_conversion_element_factory (GstPlaySinkConvertBin
    * self, const char *factory, const char *name)
{
  GstElement *el;

  el = gst_element_factory_make (factory, name);
  if (el == NULL) {
    gst_play_sink_convert_bin_post_missing_element_message (self, factory);
    GST_ELEMENT_WARNING (self, CORE, MISSING_PLUGIN,
        (_("Missing element '%s' - check your GStreamer installation."),
            factory),
        (self->audio ? "audio rendering might fail" :
            "video rendering might fail"));
  } else {
    gst_play_sink_convert_bin_add_conversion_element (self, el);
  }
  return el;
}
void
gst_phoenixsrc_set_property (GObject * object, guint property_id,
    const GValue * value, GParamSpec * pspec)
{
  GstPhoenixSrc *phoenixsrc;

  g_return_if_fail (GST_IS_PHOENIX_SRC (object));
  phoenixsrc = GST_PHOENIX_SRC (object);

  switch (property_id) {
    case PROP_CAMERA_CONFIG_FILEPATH:
      g_free (phoenixsrc->config_filepath);
      phoenixsrc->config_filepath = g_strdup (g_value_get_string (value));
      break;
    case PROP_NUM_CAPTURE_BUFFERS:
      if (phoenixsrc->acq_started) {
        GST_ELEMENT_WARNING (phoenixsrc, RESOURCE, SETTINGS,
            ("Number of capture buffers cannot be changed after acquisition has started."),
            (NULL));
      } else {
        phoenixsrc->num_capture_buffers = g_value_get_uint (value);

        g_free (phoenixsrc->frame_start_times);
        phoenixsrc->frame_start_times =
            g_new (guint64, phoenixsrc->num_capture_buffers);

        g_free (phoenixsrc->frame_end_times);
        phoenixsrc->frame_end_times =
            g_new (guint64, phoenixsrc->num_capture_buffers);
      }
      break;
    case PROP_BOARD:
      phoenixsrc->board = g_value_get_uint (value);
      break;
    case PROP_CHANNEL:
      phoenixsrc->channel = g_value_get_uint (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
  }
}
static GstFlowReturn
gst_face_blur_transform_ip (GstOpencvVideoFilter * transform,
    GstBuffer * buffer, IplImage * img)
{
  GstFaceBlur *filter = GST_FACE_BLUR (transform);
  CvSeq *faces;
  int i;

  if (!filter->cvCascade) {
    if (filter->profile != NULL
        && filter->sent_profile_load_failed_msg == FALSE) {
      GST_ELEMENT_WARNING (filter, RESOURCE, NOT_FOUND,
          ("Profile %s is missing.", filter->profile),
          ("missing faceblur profile file %s", filter->profile));
      filter->sent_profile_load_failed_msg = TRUE;
    }

    return GST_FLOW_OK;
  }

  cvCvtColor (img, filter->cvGray, CV_RGB2GRAY);
  cvClearMemStorage (filter->cvStorage);

  faces =
      cvHaarDetectObjects (filter->cvGray, filter->cvCascade,
      filter->cvStorage, filter->scale_factor, filter->min_neighbors,
      filter->flags, cvSize (filter->min_size_width, filter->min_size_height)
#if (CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >= 2)
      , cvSize (filter->min_size_width + 2, filter->min_size_height + 2)
#endif
      );

  for (i = 0; i < (faces ? faces->total : 0); i++) {
    CvRect *r = (CvRect *) cvGetSeqElem (faces, i);
    cvSetImageROI (img, *r);
    cvSmooth (img, img, CV_BLUR, 11, 11, 0, 0);
    cvSmooth (img, img, CV_GAUSSIAN, 11, 11, 0, 0);
    cvResetImageROI (img);
  }

  return GST_FLOW_OK;
}
Beispiel #6
0
static gboolean
gst_aggregator_query_latency (GstAggregator * self, GstQuery * query)
{
  LatencyData data;

  data.min = 0;
  data.max = GST_CLOCK_TIME_NONE;
  data.live = FALSE;

  /* query upstream's latency */
  gst_aggregator_iterate_sinkpads (self,
      (GstAggregatorPadForeachFunc) _latency_query, &data);

  if (data.live && GST_CLOCK_TIME_IS_VALID (self->timeout) &&
      self->timeout > data.max) {
    GST_ELEMENT_WARNING (self, CORE, NEGOTIATION,
        ("%s", "Timeout too big"),
        ("The requested timeout value is too big for the latency in the "
            "current pipeline.  Limiting to %" G_GINT64_FORMAT, data.max));
    self->timeout = data.max;
  }

  self->priv->latency_live = data.live;
  self->priv->latency_min = data.min;
  self->priv->latency_max = data.max;

  /* add our own */
  if (GST_CLOCK_TIME_IS_VALID (self->timeout)) {
    if (GST_CLOCK_TIME_IS_VALID (data.min))
      data.min += self->timeout;
    if (GST_CLOCK_TIME_IS_VALID (data.max))
      data.max += self->timeout;
  }

  GST_DEBUG_OBJECT (self, "configured latency live:%s min:%" G_GINT64_FORMAT
      " max:%" G_GINT64_FORMAT, data.live ? "true" : "false", data.min,
      data.max);

  gst_query_set_latency (query, data.live, data.min, data.max);

  return TRUE;
}
Beispiel #7
0
/**
 * gst_aggregator_set_timeout:
 * @agg: a #GstAggregator
 * @timeout: the new timeout value.
 *
 * Sets the new timeout value to @timeout. This value is used to limit the
 * amount of time a pad waits for data to appear before considering the pad
 * as unresponsive.
 */
static void
gst_aggregator_set_timeout (GstAggregator * self, gint64 timeout)
{
  g_return_if_fail (GST_IS_AGGREGATOR (self));

  GST_OBJECT_LOCK (self);

  if (self->priv->latency_live && self->priv->latency_max != 0 &&
      GST_CLOCK_TIME_IS_VALID (timeout) && timeout > self->priv->latency_max) {
    GST_ELEMENT_WARNING (self, CORE, NEGOTIATION,
        ("%s", "Timeout too big"),
        ("The requested timeout value is too big for the latency in the "
            "current pipeline.  Limiting to %" G_GINT64_FORMAT,
            self->priv->latency_max));
    timeout = self->priv->latency_max;
  }

  self->timeout = timeout;
  GST_OBJECT_UNLOCK (self);
}
Beispiel #8
0
/* We take ownership of mask here */
static void
gst_motiondetect_load_mask (StbtMotionDetect * filter, char* mask)
{
  char *oldMaskFilename = NULL;
  IplImage *oldMaskImage = NULL, *newMaskImage = NULL;

  if (mask) {
    newMaskImage = cvLoadImage (mask, CV_LOAD_IMAGE_GRAYSCALE);
    if (!newMaskImage) {
      /* Unfortunately OpenCV doesn't seem to provide any way of finding out
         why the image load failed, so we can't be more specific than FAILED: */
      GST_ELEMENT_WARNING (filter, RESOURCE, FAILED,
          ("OpenCV failed to load mask image"),
          ("While attempting to load mask '%s'", mask));
      GST_WARNING ("Couldn't load mask image: %s. error: %s",
          mask, g_strerror (errno));
      g_free (mask);
      mask = NULL;
    }
    gst_motiondetect_check_mask_compability(filter);
  }

  GST_OBJECT_LOCK(filter);
  oldMaskFilename = filter->mask;
  filter->mask = mask;
  oldMaskImage = filter->cvMaskImage;
  filter->cvMaskImage = newMaskImage;

  if (filter->cvInvertedMaskImage) {
    cvReleaseImage (&filter->cvInvertedMaskImage);
    filter->cvInvertedMaskImage = NULL;
  }
  if (filter->cvMaskImage) {
    filter->cvInvertedMaskImage = cvCloneImage (filter->cvMaskImage);
    cvNot(filter->cvMaskImage, filter->cvInvertedMaskImage);
  }
  GST_OBJECT_UNLOCK(filter);

  cvReleaseImage (&oldMaskImage);
  g_free(oldMaskFilename);
}
void
gst_play_sink_convert_bin_add_identity (GstPlaySinkConvertBin * self)
{
  if (self->identity)
    return;

  self->identity = gst_element_factory_make ("identity", "identity");
  if (self->identity == NULL) {
    gst_play_sink_convert_bin_post_missing_element_message (self, "identity");
    GST_ELEMENT_WARNING (self, CORE, MISSING_PLUGIN,
        (_("Missing element '%s' - check your GStreamer installation."),
            "identity"), (self->audio ?
            "audio rendering might fail" : "video rendering might fail")

        );
  } else {
    g_object_set (self->identity, "silent", TRUE, "signal-handoffs", FALSE,
        NULL);
    gst_bin_add (GST_BIN_CAST (self), self->identity);
  }
}
Beispiel #10
0
static GstStateChangeReturn
gst_wavenc_change_state (GstElement * element, GstStateChange transition)
{
  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
  GstWavEnc *wavenc = GST_WAVENC (element);

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      wavenc->format = 0;
      wavenc->channels = 0;
      wavenc->width = 0;
      wavenc->rate = 0;
      wavenc->length = 0;
      wavenc->sent_header = FALSE;
      /* its true because we haven't writen anything */
      wavenc->finished_properly = TRUE;
      break;
    default:
      break;
  }

  ret = parent_class->change_state (element, transition);
  if (ret != GST_STATE_CHANGE_SUCCESS)
    return ret;

  switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      if (!wavenc->finished_properly) {
        GST_ELEMENT_WARNING (wavenc, STREAM, MUX,
            ("Wav stream not finished properly"),
            ("Wav stream not finished properly, no EOS received "
                "before shutdown"));
      }
      break;
    default:
      break;
  }

  return ret;
}
static gboolean
gst_identity_query (GstBaseTransform * base, GstPadDirection direction,
    GstQuery * query)
{
  GstIdentity *identity;
  gboolean ret;

  identity = GST_IDENTITY (base);

  ret = GST_BASE_TRANSFORM_CLASS (parent_class)->query (base, direction, query);

  if (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY) {
    gboolean live = FALSE;
    GstClockTime min = 0, max = 0;

    if (ret) {
      gst_query_parse_latency (query, &live, &min, &max);

      if (identity->sync && max < min) {
        GST_ELEMENT_WARNING (base, CORE, CLOCK, (NULL),
            ("Impossible to configure latency before identity sync=true:"
                " max %" GST_TIME_FORMAT " < min %"
                GST_TIME_FORMAT ". Add queues or other buffering elements.",
                GST_TIME_ARGS (max), GST_TIME_ARGS (min)));
      }
    }

    /* Ignore the upstream latency if it is not live */
    GST_OBJECT_LOCK (identity);
    if (live)
      identity->upstream_latency = min;
    else
      identity->upstream_latency = 0;
    GST_OBJECT_UNLOCK (identity);

    gst_query_set_latency (query, live || identity->sync, min, max);
    ret = TRUE;
  }
  return ret;
}
static GstBuffer *
gst_rtp_g722_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
{
  GstRtpG722Depay *rtpg722depay;
  GstBuffer *outbuf;
  gint payload_len;
  gboolean marker;
  GstRTPBuffer rtp = { NULL };

  rtpg722depay = GST_RTP_G722_DEPAY (depayload);

  gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);

  payload_len = gst_rtp_buffer_get_payload_len (&rtp);

  if (payload_len <= 0)
    goto empty_packet;

  GST_DEBUG_OBJECT (rtpg722depay, "got payload of %d bytes", payload_len);

  outbuf = gst_rtp_buffer_get_payload_buffer (&rtp);
  marker = gst_rtp_buffer_get_marker (&rtp);
  gst_rtp_buffer_unmap (&rtp);

  if (marker && outbuf) {
    /* mark talk spurt with DISCONT */
    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
  }

  return outbuf;

  /* ERRORS */
empty_packet:
  {
    GST_ELEMENT_WARNING (rtpg722depay, STREAM, DECODE,
        ("Empty Payload."), (NULL));
    gst_rtp_buffer_unmap (&rtp);
    return NULL;
  }
}
Beispiel #13
0
gboolean
gst_v4l2_set_input (GstV4l2Object * v4l2object, gint input)
{
  GST_DEBUG_OBJECT (v4l2object->element, "trying to set input to %d", input);

  if (!GST_V4L2_IS_OPEN (v4l2object))
    return FALSE;

  if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_INPUT, &input) < 0)
    goto input_failed;

  return TRUE;

  /* ERRORS */
input_failed:
  {
    GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
        (_("Failed to set input %d on device %s."),
            input, v4l2object->videodev), GST_ERROR_SYSTEM);
    return FALSE;
  }
}
Beispiel #14
0
/******************************************************
 * gst_v4l2_set_norm()
 *   Set the norm of the current device
 * return value: TRUE on success, FALSE on error
 ******************************************************/
gboolean
gst_v4l2_set_norm (GstV4l2Object * v4l2object, v4l2_std_id norm)
{
  GST_DEBUG_OBJECT (v4l2object->element, "trying to set norm to %llx", norm);

  if (!GST_V4L2_IS_OPEN (v4l2object))
    return FALSE;

  if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_STD, &norm) < 0)
    goto std_failed;

  return TRUE;

  /* ERRORS */
std_failed:
  {
    GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
        (_("Failed to set norm for device '%s'."),
            v4l2object->videodev), GST_ERROR_SYSTEM);
    return FALSE;
  }
}
void
gst_decklink_video_sink_set_property (GObject * object, guint property_id,
    const GValue * value, GParamSpec * pspec)
{
  GstDecklinkVideoSink *self = GST_DECKLINK_VIDEO_SINK_CAST (object);

  switch (property_id) {
    case PROP_MODE:
      self->mode = (GstDecklinkModeEnum) g_value_get_enum (value);
      break;
    case PROP_DEVICE_NUMBER:
      self->device_number = g_value_get_int (value);
      break;
    case PROP_VIDEO_FORMAT:
      self->video_format = (GstDecklinkVideoFormat) g_value_get_enum (value);
      switch (self->video_format) {
        case GST_DECKLINK_VIDEO_FORMAT_AUTO:
        case GST_DECKLINK_VIDEO_FORMAT_8BIT_YUV:
        case GST_DECKLINK_VIDEO_FORMAT_10BIT_YUV:
        case GST_DECKLINK_VIDEO_FORMAT_8BIT_ARGB:
        case GST_DECKLINK_VIDEO_FORMAT_8BIT_BGRA:
          break;
        default:
          GST_ELEMENT_WARNING (GST_ELEMENT (self), CORE, NOT_IMPLEMENTED,
              ("Format %d not supported", self->video_format), (NULL));
          break;
      }
      break;
    case PROP_TIMECODE_FORMAT:
      self->timecode_format =
          gst_decklink_timecode_format_from_enum ((GstDecklinkTimecodeFormat)
          g_value_get_enum (value));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
  }
}
static void
kms_recorder_end_point_dispose (GObject * object)
{
  KmsRecorderEndPoint *self = KMS_RECORDER_END_POINT (object);

  g_clear_object (&self->priv->loop);
  g_clear_object (&self->priv->controller);

  if (self->priv->pipeline != NULL) {
    if (GST_STATE (self->priv->pipeline) != GST_STATE_NULL) {
      GST_ELEMENT_WARNING (self, RESOURCE, BUSY,
          ("Recorder may have buffers to save"),
          ("Disposing recorder when it isn't stopped."));
    }
    gst_element_set_state (self->priv->pipeline, GST_STATE_NULL);
    g_object_unref (self->priv->pipeline);
    self->priv->pipeline = NULL;
  }

  /* clean up as possible.  may be called multiple times */

  G_OBJECT_CLASS (kms_recorder_end_point_parent_class)->dispose (object);
}
static void
pad_blocked_cb (GstPad * pad, gboolean blocked, GstPlaySinkVideoConvert * self)
{
    GstPad *peer;
    GstCaps *caps;
    gboolean raw;

    GST_PLAY_SINK_VIDEO_CONVERT_LOCK (self);
    self->sink_proxypad_blocked = blocked;
    GST_DEBUG_OBJECT (self, "Pad blocked: %d", blocked);
    if (!blocked)
        goto done;

    /* There must be a peer at this point */
    peer = gst_pad_get_peer (self->sinkpad);
    caps = gst_pad_get_negotiated_caps (peer);
    if (!caps)
        caps = gst_pad_get_caps_reffed (peer);
    gst_object_unref (peer);

    raw = is_raw_caps (caps);
    GST_DEBUG_OBJECT (self, "Caps %" GST_PTR_FORMAT " are raw: %d", caps, raw);
    gst_caps_unref (caps);

    if (raw == self->raw)
        goto unblock;
    self->raw = raw;

    if (raw) {
        GstBin *bin = GST_BIN_CAST (self);
        GstElement *head = NULL, *prev = NULL;
        GstPad *pad;

        GST_DEBUG_OBJECT (self, "Creating raw conversion pipeline");

        gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->sinkpad), NULL);
        gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), NULL);

        self->conv = gst_element_factory_make ("ffmpegcolorspace", "conv");
        if (self->conv == NULL) {
            post_missing_element_message (self, "ffmpegcolorspace");
            GST_ELEMENT_WARNING (self, CORE, MISSING_PLUGIN,
                                 (_("Missing element '%s' - check your GStreamer installation."),
                                  "ffmpegcolorspace"), ("video rendering might fail"));
        } else {
            gst_bin_add (bin, self->conv);
            gst_element_sync_state_with_parent (self->conv);
            distribute_running_time (self->conv, &self->segment);
            prev = head = self->conv;
        }

        self->scale = gst_element_factory_make ("videoscale", "scale");
        if (self->scale == NULL) {
            post_missing_element_message (self, "videoscale");
            GST_ELEMENT_WARNING (self, CORE, MISSING_PLUGIN,
                                 (_("Missing element '%s' - check your GStreamer installation."),
                                  "videoscale"), ("possibly a liboil version mismatch?"));
        } else {
            /* Add black borders if necessary to keep the DAR */
            g_object_set (self->scale, "add-borders", TRUE, NULL);
            gst_bin_add (bin, self->scale);
            gst_element_sync_state_with_parent (self->scale);
            distribute_running_time (self->scale, &self->segment);
            if (prev) {
                if (!gst_element_link_pads_full (prev, "src", self->scale, "sink",
                                                 GST_PAD_LINK_CHECK_TEMPLATE_CAPS))
                    goto link_failed;
            } else {
                head = self->scale;
            }
            prev = self->scale;
        }

        if (head) {
            pad = gst_element_get_static_pad (head, "sink");
            gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->sinkpad), pad);
            gst_object_unref (pad);
        }

        if (prev) {
            pad = gst_element_get_static_pad (prev, "src");
            gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), pad);
            gst_object_unref (pad);
        }

        if (!head && !prev) {
            gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad),
                                      self->sink_proxypad);
        }

        GST_DEBUG_OBJECT (self, "Raw conversion pipeline created");
    } else {
        GstBin *bin = GST_BIN_CAST (self);

        GST_DEBUG_OBJECT (self, "Removing raw conversion pipeline");

        gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->sinkpad), NULL);
        gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), NULL);

        if (self->conv) {
            gst_element_set_state (self->conv, GST_STATE_NULL);
            gst_bin_remove (bin, self->conv);
            self->conv = NULL;
        }
        if (self->scale) {
            gst_element_set_state (self->scale, GST_STATE_NULL);
            gst_bin_remove (bin, self->scale);
            self->scale = NULL;
        }

        gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad),
                                  self->sink_proxypad);

        GST_DEBUG_OBJECT (self, "Raw conversion pipeline removed");
    }

unblock:
    gst_pad_set_blocked_async_full (self->sink_proxypad, FALSE,
                                    (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self),
                                    (GDestroyNotify) gst_object_unref);

done:
    GST_PLAY_SINK_VIDEO_CONVERT_UNLOCK (self);
    return;

link_failed:
    {
        GST_ELEMENT_ERROR (self, CORE, PAD,
                           (NULL), ("Failed to configure the video converter."));
        gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad),
                                  self->sink_proxypad);
        gst_pad_set_blocked_async_full (self->sink_proxypad, FALSE,
                                        (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self),
                                        (GDestroyNotify) gst_object_unref);
        return;
    }
}
Beispiel #18
0
static GstFlowReturn
gst_opus_dec_parse_header (GstOpusDec * dec, GstBuffer * buf)
{
  const guint8 *data;
  GstAudioChannelPosition pos[64];
  const GstAudioChannelPosition *posn = NULL;
  GstMapInfo map;

  if (!gst_opus_header_is_id_header (buf)) {
    GST_ERROR_OBJECT (dec, "Header is not an Opus ID header");
    return GST_FLOW_ERROR;
  }

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

  if (!(dec->n_channels == 0 || dec->n_channels == data[9])) {
    gst_buffer_unmap (buf, &map);
    GST_ERROR_OBJECT (dec, "Opus ID header has invalid channels");
    return GST_FLOW_ERROR;
  }

  dec->n_channels = data[9];
  dec->sample_rate = GST_READ_UINT32_LE (data + 12);
  dec->pre_skip = GST_READ_UINT16_LE (data + 10);
  dec->r128_gain = GST_READ_UINT16_LE (data + 16);
  dec->r128_gain_volume = gst_opus_dec_get_r128_volume (dec->r128_gain);
  GST_INFO_OBJECT (dec,
      "Found pre-skip of %u samples, R128 gain %d (volume %f)",
      dec->pre_skip, dec->r128_gain, dec->r128_gain_volume);

  dec->channel_mapping_family = data[18];
  if (dec->channel_mapping_family == 0) {
    /* implicit mapping */
    GST_INFO_OBJECT (dec, "Channel mapping family 0, implicit mapping");
    dec->n_streams = dec->n_stereo_streams = 1;
    dec->channel_mapping[0] = 0;
    dec->channel_mapping[1] = 1;
  } else {
    dec->n_streams = data[19];
    dec->n_stereo_streams = data[20];
    memcpy (dec->channel_mapping, data + 21, dec->n_channels);

    if (dec->channel_mapping_family == 1) {
      GST_INFO_OBJECT (dec, "Channel mapping family 1, Vorbis mapping");
      switch (dec->n_channels) {
        case 1:
        case 2:
          /* nothing */
          break;
        case 3:
        case 4:
        case 5:
        case 6:
        case 7:
        case 8:
          posn = gst_opus_channel_positions[dec->n_channels - 1];
          break;
        default:{
          gint i;

          GST_ELEMENT_WARNING (GST_ELEMENT (dec), STREAM, DECODE,
              (NULL), ("Using NONE channel layout for more than 8 channels"));

          for (i = 0; i < dec->n_channels; i++)
            pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE;

          posn = pos;
        }
      }
    } else {
      GST_INFO_OBJECT (dec, "Channel mapping family %d",
          dec->channel_mapping_family);
    }
  }

  gst_opus_dec_negotiate (dec, posn);

  gst_buffer_unmap (buf, &map);

  return GST_FLOW_OK;
}
static GstBuffer *
gst_rtp_j2k_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
{
  GstRtpJ2KDepay *rtpj2kdepay;
  guint8 *payload;
  guint MHF, mh_id, frag_offset, tile, payload_len, j2klen;
  gint gap;
  guint32 rtptime;

  rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload);

  payload = gst_rtp_buffer_get_payload (buf);
  payload_len = gst_rtp_buffer_get_payload_len (buf);

  /* we need at least a header */
  if (payload_len < 8)
    goto empty_packet;

  rtptime = gst_rtp_buffer_get_timestamp (buf);

  /* new timestamp marks new frame */
  if (rtpj2kdepay->last_rtptime != rtptime) {
    rtpj2kdepay->last_rtptime = rtptime;
    /* flush pending frame */
    gst_rtp_j2k_depay_flush_frame (depayload);
  }

  /*
   *  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
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |tp |MHF|mh_id|T|     priority  |           tile number         |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |reserved       |             fragment offset                   |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   */
  MHF = (payload[0] & 0x30) >> 4;
  mh_id = (payload[0] & 0xe) >> 1;

  if (rtpj2kdepay->last_mh_id == -1)
    rtpj2kdepay->last_mh_id = mh_id;
  else if (rtpj2kdepay->last_mh_id != mh_id)
    goto wrong_mh_id;

  tile = (payload[2] << 8) | payload[3];
  frag_offset = (payload[5] << 16) | (payload[6] << 8) | payload[7];
  j2klen = payload_len - 8;

  GST_DEBUG_OBJECT (rtpj2kdepay, "MHF %u, tile %u, frag %u, expected %u", MHF,
      tile, frag_offset, rtpj2kdepay->next_frag);

  /* calculate the gap between expected frag */
  gap = frag_offset - rtpj2kdepay->next_frag;
  /* calculate next frag */
  rtpj2kdepay->next_frag = frag_offset + j2klen;

  if (gap != 0) {
    GST_DEBUG_OBJECT (rtpj2kdepay, "discont of %d, clear PU", gap);
    /* discont, clear pu adapter and resync */
    gst_rtp_j2k_depay_clear_pu (rtpj2kdepay);
  }

  /* check for sync code */
  if (j2klen > 2 && payload[8] == 0xff) {
    guint marker = payload[9];

    /* packets must start with SOC, SOT or SOP */
    switch (marker) {
      case J2K_MARKER_SOC:
        GST_DEBUG_OBJECT (rtpj2kdepay, "found SOC packet");
        /* flush the previous frame, should have happened when the timestamp
         * changed above. */
        gst_rtp_j2k_depay_flush_frame (depayload);
        rtpj2kdepay->have_sync = TRUE;
        break;
      case J2K_MARKER_SOT:
        /* flush the previous tile */
        gst_rtp_j2k_depay_flush_tile (depayload);
        GST_DEBUG_OBJECT (rtpj2kdepay, "found SOT packet");
        rtpj2kdepay->have_sync = TRUE;
        /* we sync on the tile now */
        rtpj2kdepay->last_tile = tile;
        break;
      case J2K_MARKER_SOP:
        GST_DEBUG_OBJECT (rtpj2kdepay, "found SOP packet");
        /* flush the previous PU */
        gst_rtp_j2k_depay_flush_pu (depayload);
        if (rtpj2kdepay->last_tile != tile) {
          /* wrong tile, we lose sync and we need a new SOT or SOC to regain
           * sync. First flush out the previous tile if we have one. */
          if (rtpj2kdepay->last_tile != -1)
            gst_rtp_j2k_depay_flush_tile (depayload);
          /* now we have no more valid tile and no sync */
          rtpj2kdepay->last_tile = -1;
          rtpj2kdepay->have_sync = FALSE;
        } else {
          rtpj2kdepay->have_sync = TRUE;
        }
        break;
      default:
        GST_DEBUG_OBJECT (rtpj2kdepay, "no sync packet 0x%02d", marker);
        break;
    }
  }

  if (rtpj2kdepay->have_sync) {
    GstBuffer *pu_frag;

    if (gst_adapter_available (rtpj2kdepay->pu_adapter) == 0) {
      /* first part of pu, record state */
      GST_DEBUG_OBJECT (rtpj2kdepay, "first PU");
      rtpj2kdepay->pu_MHF = MHF;
    }
    /* and push in pu adapter */
    GST_DEBUG_OBJECT (rtpj2kdepay, "push pu of size %u in adapter", j2klen);
    pu_frag = gst_rtp_buffer_get_payload_subbuffer (buf, 8, -1);
    gst_adapter_push (rtpj2kdepay->pu_adapter, pu_frag);

    if (MHF & 2) {
      /* last part of main header received, we can flush it */
      GST_DEBUG_OBJECT (rtpj2kdepay, "header end, flush pu");
      gst_rtp_j2k_depay_flush_pu (depayload);
    }
  } else {
    GST_DEBUG_OBJECT (rtpj2kdepay, "discard packet, no sync");
  }

  /* marker bit finishes the frame */
  if (gst_rtp_buffer_get_marker (buf)) {
    GST_DEBUG_OBJECT (rtpj2kdepay, "marker set, last buffer");
    /* then flush frame */
    gst_rtp_j2k_depay_flush_frame (depayload);
  }
  return NULL;

  /* ERRORS */
empty_packet:
  {
    GST_ELEMENT_WARNING (rtpj2kdepay, STREAM, DECODE,
        ("Empty Payload."), (NULL));
    return NULL;
  }
wrong_mh_id:
  {
    GST_ELEMENT_WARNING (rtpj2kdepay, STREAM, DECODE,
        ("Invalid mh_id %u, expected %u", mh_id, rtpj2kdepay->last_mh_id),
        (NULL));
    gst_rtp_j2k_depay_clear_pu (rtpj2kdepay);
    return NULL;
  }
}
static GstFlowReturn
gst_rtp_j2k_depay_flush_tile (GstBaseRTPDepayload * depayload)
{
  GstRtpJ2KDepay *rtpj2kdepay;
  guint avail, mh_id;
  GList *packets, *walk;
  guint8 end[2];
  GstFlowReturn ret = GST_FLOW_OK;

  rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload);

  /* flush pending PU */
  gst_rtp_j2k_depay_flush_pu (depayload);

  /* take all available buffers */
  avail = gst_adapter_available (rtpj2kdepay->t_adapter);
  if (avail == 0)
    goto done;

  mh_id = rtpj2kdepay->last_mh_id;

  GST_DEBUG_OBJECT (rtpj2kdepay, "flushing tile of size %u", avail);

  if (gst_adapter_available (rtpj2kdepay->f_adapter) == 0) {
    GstBuffer *mheader;

    /* we need a header now */
    if ((mheader = rtpj2kdepay->MH[mh_id]) == NULL)
      goto waiting_header;

    /* push header in the adapter */
    GST_DEBUG_OBJECT (rtpj2kdepay, "pushing header %u", mh_id);
    gst_adapter_push (rtpj2kdepay->f_adapter, gst_buffer_ref (mheader));
  }

  /* check for last bytes */
  gst_adapter_copy (rtpj2kdepay->t_adapter, end, avail - 2, 2);

  /* now append the tile packets to the frame */
  packets = gst_adapter_take_list (rtpj2kdepay->t_adapter, avail);
  for (walk = packets; walk; walk = g_list_next (walk)) {
    GstBuffer *buf = GST_BUFFER_CAST (walk->data);

    if (walk == packets) {
      guint8 *data;
      guint size;

      /* first buffer should contain the SOT */
      data = GST_BUFFER_DATA (buf);
      size = GST_BUFFER_SIZE (buf);

      if (size < 12)
        goto invalid_tile;

      if (data[0] == 0xff && data[1] == J2K_MARKER_SOT) {
        guint Psot, nPsot;

        if (end[0] == 0xff && end[1] == J2K_MARKER_EOC)
          nPsot = avail - 2;
        else
          nPsot = avail;

        Psot = GST_READ_UINT32_BE (&data[6]);
        if (Psot != nPsot && Psot != 0) {
          /* Psot must match the size of the tile */
          GST_DEBUG_OBJECT (rtpj2kdepay, "set Psot from %u to %u", Psot, nPsot);
          buf = gst_buffer_make_writable (buf);
          data = GST_BUFFER_DATA (buf);
          GST_WRITE_UINT32_BE (&data[6], nPsot);
        }
      }
    }

    GST_DEBUG_OBJECT (rtpj2kdepay, "append pu packet of size %u",
        GST_BUFFER_SIZE (buf));
    gst_adapter_push (rtpj2kdepay->f_adapter, buf);
  }
  g_list_free (packets);

done:
  rtpj2kdepay->last_tile = -1;

  return ret;

  /* errors */
waiting_header:
  {
    GST_DEBUG_OBJECT (rtpj2kdepay, "waiting for header %u", mh_id);
    gst_adapter_clear (rtpj2kdepay->t_adapter);
    rtpj2kdepay->last_tile = -1;
    return ret;
  }
invalid_tile:
  {
    GST_ELEMENT_WARNING (rtpj2kdepay, STREAM, DECODE, ("Invalid tile"), (NULL));
    gst_adapter_clear (rtpj2kdepay->t_adapter);
    rtpj2kdepay->last_tile = -1;
    return ret;
  }
}
/* create a socket for sending to remote machine */
static void
gst_sctp_base_sink_create_socket (GstSCTPBaseSink * self)
{
  GSocketAddress *saddr;
  GResolver *resolver;
  GInetAddress *addr;
  GError *err = NULL;

  if (GST_OBJECT_FLAG_IS_SET (self, GST_SCTP_BASE_SINK_OPEN))
    return;

  /* look up name if we need to */
  addr = g_inet_address_new_from_string (self->priv->host);
  if (addr == NULL) {
    GList *results;

    resolver = g_resolver_get_default ();
    results = g_resolver_lookup_by_name (resolver, self->priv->host,
        self->priv->cancellable, &err);

    if (results == NULL)
      goto name_resolve;

    addr = G_INET_ADDRESS (g_object_ref (results->data));

    g_resolver_free_addresses (results);
    g_object_unref (resolver);
  }

  if (G_UNLIKELY (GST_LEVEL_DEBUG <= _gst_debug_min)) {
    gchar *ip = g_inet_address_to_string (addr);

    GST_DEBUG_OBJECT (self, "IP address for host %s is %s", self->priv->host,
        ip);
    g_free (ip);
  }

  saddr = g_inet_socket_address_new (addr, self->priv->port);
  g_object_unref (addr);

  /* create sending client socket */
  GST_DEBUG_OBJECT (self, "opening sending client socket to %s:%d",
      self->priv->host, self->priv->port);

  self->priv->socket = g_socket_new (g_socket_address_get_family (saddr),
      G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_SCTP, &err);
  if (self->priv->socket == NULL)
    goto no_socket;

#if defined (SCTP_INITMSG)
  {
    struct sctp_initmsg initmsg;

    memset (&initmsg, 0, sizeof (initmsg));
    initmsg.sinit_num_ostreams = self->priv->num_ostreams;
    initmsg.sinit_max_instreams = self->priv->max_istreams;

    if (setsockopt (g_socket_get_fd (self->priv->socket), IPPROTO_SCTP,
            SCTP_INITMSG, &initmsg, sizeof (initmsg)) < 0)
      GST_ELEMENT_WARNING (self, RESOURCE, SETTINGS, (NULL),
          ("Could not configure SCTP socket: %s (%d)", g_strerror (errno),
              errno));
  }
#else
  GST_WARNING_OBJECT (self, "don't know how to configure the SCTP initiation "
      "parameters on this OS.");
#endif

  GST_DEBUG_OBJECT (self, "opened sending client socket");

  /* connect to server */
  if (!g_socket_connect (self->priv->socket, saddr, self->priv->cancellable,
          &err))
    goto connect_failed;

  g_object_unref (saddr);

  GST_OBJECT_FLAG_SET (self, GST_SCTP_BASE_SINK_OPEN);
  GST_DEBUG ("Created sctp socket");

  return;

no_socket:
  {
    GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ, (NULL),
        ("Failed to create socket: %s", err->message));
    g_clear_error (&err);
    g_object_unref (saddr);
    return;
  }
name_resolve:
  {
    if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
      GST_DEBUG_OBJECT (self, "Cancelled name resolval");
    } else {
      GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ, (NULL),
          ("Failed to resolve host '%s': %s", self->priv->host, err->message));
    }
    g_clear_error (&err);
    g_object_unref (resolver);
    return;
  }
connect_failed:
  {
    if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
      GST_DEBUG_OBJECT (self, "Cancelled connecting");
    } else {
      GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ, (NULL),
          ("Failed to connect to host '%s:%d': %s", self->priv->host,
              self->priv->port, err->message));
    }
    g_clear_error (&err);
    g_object_unref (saddr);
    /* pretend we opened ok for proper cleanup to happen */
    GST_OBJECT_FLAG_SET (self, GST_SCTP_BASE_SINK_OPEN);
    gst_sctp_base_sink_destroy_socket (self);
    return;
  }
}
static GstBuffer *
gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstRTPBuffer * rtp)
{
  GstRtpJPEGDepay *rtpjpegdepay;
  GstBuffer *outbuf;
  gint payload_len, header_len;
  guint8 *payload;
  guint frag_offset;
  gint Q;
  guint type, width, height;
  guint16 dri, precision, length;
  guint8 *qtable;

  rtpjpegdepay = GST_RTP_JPEG_DEPAY (depayload);

  if (GST_BUFFER_IS_DISCONT (rtp->buffer)) {
    GST_DEBUG_OBJECT (depayload, "DISCONT, reset adapter");
    gst_adapter_clear (rtpjpegdepay->adapter);
    rtpjpegdepay->discont = TRUE;
  }

  payload_len = gst_rtp_buffer_get_payload_len (rtp);

  if (payload_len < 8)
    goto empty_packet;

  payload = gst_rtp_buffer_get_payload (rtp);
  header_len = 0;

  /*  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
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * | Type-specific |              Fragment Offset                  |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |      Type     |       Q       |     Width     |     Height    |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   */
  frag_offset = (payload[1] << 16) | (payload[2] << 8) | payload[3];
  type = payload[4];
  Q = payload[5];
  width = payload[6] * 8;
  height = payload[7] * 8;

  /* saw a packet with fragment offset > 0 and we don't already have data queued
   * up (most importantly, we don't have a header for this data) -- drop it
   * XXX: maybe we can check if the jpeg is progressive and salvage the data?
   * XXX: not implemented yet because jpegenc can't create progressive jpegs */
  if (frag_offset > 0 && gst_adapter_available (rtpjpegdepay->adapter) == 0)
    goto no_header_packet;

  /* allow frame dimensions > 2040, passed in SDP session or media attributes
   * from gstrtspsrc.c (gst_rtspsrc_sdp_attributes_to_caps), or in caps */
  if (!width)
    width = rtpjpegdepay->media_width;

  if (!height)
    height = rtpjpegdepay->media_height;

  if (width == 0 || height == 0)
    goto invalid_dimension;

  GST_DEBUG_OBJECT (rtpjpegdepay, "frag %u, type %u, Q %d, width %u, height %u",
      frag_offset, type, Q, width, height);

  header_len += 8;
  payload += 8;
  payload_len -= 8;

  dri = 0;
  if (type > 63) {
    if (payload_len < 4)
      goto empty_packet;

    /*  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
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     * |       Restart Interval        |F|L|       Restart Count       |
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     */
    dri = (payload[0] << 8) | payload[1];

    GST_DEBUG_OBJECT (rtpjpegdepay, "DRI %" G_GUINT16_FORMAT, dri);

    payload += 4;
    header_len += 4;
    payload_len -= 4;
  }

  if (Q >= 128 && frag_offset == 0) {
    if (payload_len < 4)
      goto empty_packet;

    /*  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      |   Precision   |             Length            |
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     * |                    Quantization Table Data                    |
     * |                              ...                              |
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     */
    precision = payload[1];
    length = (payload[2] << 8) | payload[3];

    GST_DEBUG_OBJECT (rtpjpegdepay, "precision %04x, length %" G_GUINT16_FORMAT,
        precision, length);

    if (Q == 255 && length == 0)
      goto empty_packet;

    payload += 4;
    header_len += 4;
    payload_len -= 4;

    if (length > payload_len)
      goto empty_packet;

    if (length > 0)
      qtable = payload;
    else
      qtable = rtpjpegdepay->qtables[Q];

    payload += length;
    header_len += length;
    payload_len -= length;
  } else {
    length = 0;
    qtable = NULL;
    precision = 0;
  }

  if (frag_offset == 0) {
    GstMapInfo map;
    guint size;

    if (rtpjpegdepay->width != width || rtpjpegdepay->height != height) {
      GstCaps *outcaps;

      outcaps =
          gst_caps_new_simple ("image/jpeg", "framerate", GST_TYPE_FRACTION,
          rtpjpegdepay->frate_num, rtpjpegdepay->frate_denom, "width",
          G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
      gst_pad_set_caps (depayload->srcpad, outcaps);
      gst_caps_unref (outcaps);

      rtpjpegdepay->width = width;
      rtpjpegdepay->height = height;
    }

    GST_LOG_OBJECT (rtpjpegdepay, "first packet, length %" G_GUINT16_FORMAT,
        length);

    /* first packet */
    if (length == 0) {
      if (Q < 128) {
        /* no quant table, see if we have one cached */
        qtable = rtpjpegdepay->qtables[Q];
        if (!qtable) {
          GST_DEBUG_OBJECT (rtpjpegdepay, "making Q %d table", Q);
          /* make and cache the table */
          qtable = g_new (guint8, 128);
          MakeTables (rtpjpegdepay, Q, qtable);
          rtpjpegdepay->qtables[Q] = qtable;
        } else {
          GST_DEBUG_OBJECT (rtpjpegdepay, "using cached table for Q %d", Q);
        }
        /* all 8 bit quantizers */
        precision = 0;
      } else {
        if (!qtable)
          goto no_qtable;
      }
    }

    /* I think we can get here with a NULL qtable, so make sure we don't
       go dereferencing it in MakeHeaders if we do */
    if (!qtable)
      goto no_qtable;

    /* max header length, should be big enough */
    outbuf = gst_buffer_new_and_alloc (1000);
    gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
    size = MakeHeaders (map.data, type, width, height, qtable, precision, dri);
    gst_buffer_unmap (outbuf, &map);
    gst_buffer_resize (outbuf, 0, size);

    GST_DEBUG_OBJECT (rtpjpegdepay, "pushing %u bytes of header", size);

    gst_adapter_push (rtpjpegdepay->adapter, outbuf);
  }

  /* take JPEG data, push in the adapter */
  GST_DEBUG_OBJECT (rtpjpegdepay, "pushing data at offset %d", header_len);
  outbuf = gst_rtp_buffer_get_payload_subbuffer (rtp, header_len, -1);
  gst_adapter_push (rtpjpegdepay->adapter, outbuf);
  outbuf = NULL;

  if (gst_rtp_buffer_get_marker (rtp)) {
    guint avail;
    guint8 end[2];
    GstMapInfo map;

    /* last buffer take all data out of the adapter */
    avail = gst_adapter_available (rtpjpegdepay->adapter);
    GST_DEBUG_OBJECT (rtpjpegdepay, "marker set, last buffer");

    if (avail < 2)
      goto invalid_packet;

    /* take the last bytes of the jpeg data to see if there is an EOI
     * marker */
    gst_adapter_copy (rtpjpegdepay->adapter, end, avail - 2, 2);

    if (end[0] != 0xff && end[1] != 0xd9) {
      GST_DEBUG_OBJECT (rtpjpegdepay, "no EOI marker, adding one");

      /* no EOI marker, add one */
      outbuf = gst_buffer_new_and_alloc (2);
      gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
      map.data[0] = 0xff;
      map.data[1] = 0xd9;
      gst_buffer_unmap (outbuf, &map);

      gst_adapter_push (rtpjpegdepay->adapter, outbuf);
      avail += 2;
    }
    outbuf = gst_adapter_take_buffer (rtpjpegdepay->adapter, avail);

    if (rtpjpegdepay->discont) {
      GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
      rtpjpegdepay->discont = FALSE;
    }

    gst_rtp_drop_meta (GST_ELEMENT_CAST (rtpjpegdepay), outbuf,
        g_quark_from_static_string (GST_META_TAG_VIDEO_STR));

    GST_DEBUG_OBJECT (rtpjpegdepay, "returning %u bytes", avail);
  }

  return outbuf;

  /* ERRORS */
empty_packet:
  {
    GST_ELEMENT_WARNING (rtpjpegdepay, STREAM, DECODE,
        ("Empty Payload."), (NULL));
    return NULL;
  }
invalid_dimension:
  {
    GST_ELEMENT_WARNING (rtpjpegdepay, STREAM, FORMAT,
        ("Invalid Dimension %dx%d.", width, height), (NULL));
    return NULL;
  }
no_qtable:
  {
    GST_WARNING_OBJECT (rtpjpegdepay, "no qtable");
    return NULL;
  }
invalid_packet:
  {
    GST_WARNING_OBJECT (rtpjpegdepay, "invalid packet");
    gst_adapter_flush (rtpjpegdepay->adapter,
        gst_adapter_available (rtpjpegdepay->adapter));
    return NULL;
  }
no_header_packet:
  {
    GST_WARNING_OBJECT (rtpjpegdepay,
        "discarding data packets received when we have no header");
    return NULL;
  }
}
/* allocate a buffer and setup resources to process the audio samples of
 * the format as specified in @spec.
 *
 * We allocate N jack ports, one for each channel. If we are asked to
 * automatically make a connection with physical ports, we connect as many
 * ports as there are physical ports, leaving leftover ports unconnected.
 *
 * It is assumed that samplerate and number of channels are acceptable since our
 * getcaps method will always provide correct values. If unacceptable caps are
 * received for some reason, we fail here.
 */
static gboolean
gst_jack_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
{
  GstJackAudioSrc *src;
  GstJackRingBuffer *abuf;
  const char **ports;
  gint sample_rate, buffer_size;
  gint i, channels, res;
  jack_client_t *client;

  src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf));
  abuf = GST_JACK_RING_BUFFER_CAST (buf);

  GST_DEBUG_OBJECT (src, "acquire");

  client = gst_jack_audio_client_get_client (src->client);

  /* sample rate must be that of the server */
  sample_rate = jack_get_sample_rate (client);
  if (sample_rate != spec->rate)
    goto wrong_samplerate;

  channels = spec->channels;

  if (!gst_jack_audio_src_allocate_channels (src, channels))
    goto out_of_ports;

  buffer_size = jack_get_buffer_size (client);

  /* the segment size in bytes, this is large enough to hold a buffer of 32bit floats
   * for all channels  */
  spec->segsize = buffer_size * sizeof (gfloat) * channels;
  spec->latency_time = gst_util_uint64_scale (spec->segsize,
      (GST_SECOND / GST_USECOND), spec->rate * spec->bytes_per_sample);
  /* segtotal based on buffer-time latency */
  spec->segtotal = spec->buffer_time / spec->latency_time;

  GST_DEBUG_OBJECT (src, "segsize %d, segtotal %d", spec->segsize,
      spec->segtotal);

  /* allocate the ringbuffer memory now */
  buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize);
  memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data));

  if ((res = gst_jack_audio_client_set_active (src->client, TRUE)))
    goto could_not_activate;

  /* if we need to automatically connect the ports, do so now. We must do this
   * after activating the client. */
  if (src->connect == GST_JACK_CONNECT_AUTO) {
    /* find all the physical output ports. A physical output port is a port
     * associated with a hardware device. Someone needs connect to a physical
     * port in order to capture something. */
    ports =
        jack_get_ports (client, NULL, NULL,
        JackPortIsPhysical | JackPortIsOutput);
    if (ports == NULL) {
      /* no ports? fine then we don't do anything except for posting a warning
       * message. */
      GST_ELEMENT_WARNING (src, RESOURCE, NOT_FOUND, (NULL),
          ("No physical output ports found, leaving ports unconnected"));
      goto done;
    }

    for (i = 0; i < channels; i++) {
      /* stop when all output ports are exhausted */
      if (ports[i] == NULL) {
        /* post a warning that we could not connect all ports */
        GST_ELEMENT_WARNING (src, RESOURCE, NOT_FOUND, (NULL),
            ("No more physical ports, leaving some ports unconnected"));
        break;
      }
      GST_DEBUG_OBJECT (src, "try connecting to %s",
          jack_port_name (src->ports[i]));
      /* connect the physical port to a port */

      res = jack_connect (client, ports[i], jack_port_name (src->ports[i]));
      g_print ("connecting to %s\n", jack_port_name (src->ports[i]));
      if (res != 0 && res != EEXIST)
        goto cannot_connect;
    }
    free (ports);
  }
done:

  abuf->sample_rate = sample_rate;
  abuf->buffer_size = buffer_size;
  abuf->channels = spec->channels;

  return TRUE;

  /* ERRORS */
wrong_samplerate:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
        ("Wrong samplerate, server is running at %d and we received %d",
            sample_rate, spec->rate));
    return FALSE;
  }
out_of_ports:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
        ("Cannot allocate more Jack ports"));
    return FALSE;
  }
could_not_activate:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
        ("Could not activate client (%d:%s)", res, g_strerror (res)));
    return FALSE;
  }
cannot_connect:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
        ("Could not connect input ports to physical ports (%d:%s)",
            res, g_strerror (res)));
    free (ports);
    return FALSE;
  }
}
Beispiel #24
0
static void
demux_pad_added (GstElement * element, GstPad * pad, RsnDvdBin * dvdbin)
{
  gboolean skip_mq = FALSE;
  GstPad *mq_pad = NULL;
  GstPad *dest_pad = NULL;
  GstCaps *caps;
  GstStructure *s;

  GST_DEBUG_OBJECT (dvdbin, "New pad: %" GST_PTR_FORMAT, pad);

  caps = gst_pad_get_caps (pad);
  if (caps == NULL) {
    GST_WARNING_OBJECT (dvdbin, "NULL caps from pad %" GST_PTR_FORMAT, pad);
    return;
  }
  if (!gst_caps_is_fixed (caps)) {
    GST_WARNING_OBJECT (dvdbin, "Unfixed caps %" GST_PTR_FORMAT
        " on pad %" GST_PTR_FORMAT, caps, pad);
    gst_caps_unref (caps);
    return;
  }

  GST_DEBUG_OBJECT (dvdbin,
      "Pad %" GST_PTR_FORMAT " has caps: %" GST_PTR_FORMAT, pad, caps);

  s = gst_caps_get_structure (caps, 0);
  g_return_if_fail (s != NULL);

  if (can_sink_caps (dvdbin->pieces[DVD_ELEM_VIDDEC], caps)) {
    dest_pad =
        gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_VIDDEC], "sink");
  } else if (g_str_equal (gst_structure_get_name (s), "video/x-dvd-subpicture")) {
    dest_pad =
        gst_element_get_request_pad (dvdbin->pieces[DVD_ELEM_SPU_SELECT],
        "sink%d");
    skip_mq = TRUE;
  } else if (can_sink_caps (dvdbin->pieces[DVD_ELEM_AUDDEC], caps)) {
    GST_LOG_OBJECT (dvdbin, "Found audio pad w/ caps %" GST_PTR_FORMAT, caps);
    dest_pad =
        gst_element_get_request_pad (dvdbin->pieces[DVD_ELEM_AUD_SELECT],
        "sink%d");
  } else {
    GstStructure *s;

    GST_DEBUG_OBJECT (dvdbin, "Ignoring unusable pad w/ caps %" GST_PTR_FORMAT,
        caps);
    gst_element_post_message (GST_ELEMENT_CAST (dvdbin),
        gst_missing_decoder_message_new (GST_ELEMENT_CAST (dvdbin), caps));

    s = gst_caps_get_structure (caps, 0);
    if (g_str_has_prefix ("video/", gst_structure_get_name (s))) {
      GST_ELEMENT_ERROR (dvdbin, STREAM, CODEC_NOT_FOUND, (NULL),
          ("No MPEG video decoder found"));
    } else {
      GST_ELEMENT_WARNING (dvdbin, STREAM, CODEC_NOT_FOUND, (NULL),
          ("No MPEG video decoder found"));
    }
  }

  gst_caps_unref (caps);

  if (dest_pad == NULL) {
    GST_DEBUG_OBJECT (dvdbin, "Don't know how to handle pad. Ignoring");
    return;
  }

  if (skip_mq) {
    mq_pad = gst_object_ref (pad);
  } else {
    mq_pad = connect_thru_mq (dvdbin, pad);
    if (mq_pad == NULL)
      goto failed;
    GST_DEBUG_OBJECT (dvdbin, "Linking new pad %" GST_PTR_FORMAT
        " through multiqueue to %" GST_PTR_FORMAT, pad, dest_pad);
  }

  gst_pad_link (mq_pad, dest_pad);

  gst_object_unref (mq_pad);
  gst_object_unref (dest_pad);

  return;
failed:
  GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
      ("Failed to handle new demuxer pad %s", GST_PAD_NAME (pad)));
  if (mq_pad)
    gst_object_unref (mq_pad);
  if (dest_pad)
    gst_object_unref (dest_pad);
  return;
}
Beispiel #25
0
static GstBuffer *
gst_rtp_sv3v_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
{

  GstRtpSV3VDepay *rtpsv3vdepay;
  GstBuffer *outbuf;
  guint16 seq;

  rtpsv3vdepay = GST_RTP_SV3V_DEPAY (depayload);

  if (!gst_rtp_buffer_validate (buf))
    goto bad_packet;

  /* flush on sequence number gaps */
  seq = gst_rtp_buffer_get_seq (buf);
  if (seq != rtpsv3vdepay->nextseq) {
    gst_adapter_clear (rtpsv3vdepay->adapter);
  }
  rtpsv3vdepay->nextseq = seq + 1;

  {
    gint payload_len;
    guint8 *payload;
    gboolean M;
    gboolean C, S, E;

    payload_len = gst_rtp_buffer_get_payload_len (buf);
    if (payload_len < 3)
      goto bad_packet;

    payload = gst_rtp_buffer_get_payload (buf);

    M = gst_rtp_buffer_get_marker (buf);

    /* This is all a guess:
     *                      1 1 1 1 1 1
     *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     * |0|C|S|E|0|0|0|0|0|0|0|0|0|0|0|0|
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     *
     * C: config, packet contains config info
     * S: start, packet contains start of frame
     * E: end, packet contains end of frame
     */
    /* this seems to indicate a packet with a config string sent before each
     * keyframe */
    C = (payload[0] & 0x40) == 0x40;

    /* redundant with the RTP marker bit */
    S = (payload[0] & 0x20) == 0x20;
    E = (payload[0] & 0x10) == 0x10;

    if (C) {
      GstCaps *caps;
      GstBuffer *codec_data;
      GValue value = { 0 };

      /* if we already have caps, we don't need to do anything. FIXME, check if
       * something changed. */
      if (GST_PAD_CAPS (GST_BASE_RTP_DEPAYLOAD_SRCPAD (depayload)))
        return NULL;

      /* No idea... These are the two examples I found.. */
      if (payload[2] == 0x1d) {
        rtpsv3vdepay->width = 160;
        rtpsv3vdepay->height = 128;
      } else if (payload[2] == 0xdd) {
        rtpsv3vdepay->width = 320;
        rtpsv3vdepay->height = 240;
      }

      /* we need a dummy empty codec data */
      g_value_init (&value, GST_TYPE_BUFFER);
      gst_value_deserialize (&value, "");
      codec_data = gst_value_get_buffer (&value);

      caps = gst_caps_new_simple ("video/x-svq",
          "svqversion", G_TYPE_INT, 3,
          "width", G_TYPE_INT, rtpsv3vdepay->width,
          "height", G_TYPE_INT, rtpsv3vdepay->height,
          "codec_data", GST_TYPE_BUFFER, codec_data, NULL);
      gst_pad_set_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (depayload), caps);
      gst_caps_unref (caps);
      g_value_unset (&value);

      return NULL;
    }

    /* store data in adapter, stip off 2 bytes header */
    outbuf = gst_rtp_buffer_get_payload_subbuffer (buf, 2, -1);
    gst_adapter_push (rtpsv3vdepay->adapter, outbuf);

    if (M) {
      /* frame is completed: push contents of adapter */
      guint avail;

      avail = gst_adapter_available (rtpsv3vdepay->adapter);
      outbuf = gst_adapter_take_buffer (rtpsv3vdepay->adapter, avail);

      /* timestamp for complete buffer is that of last buffer as well */
      gst_buffer_set_caps (outbuf, GST_PAD_CAPS (depayload->srcpad));

      return outbuf;
    }
  }
  return NULL;

  /* ERRORS */
bad_packet:
  {
    GST_ELEMENT_WARNING (rtpsv3vdepay, STREAM, DECODE,
        ("Packet did not validate"), (NULL));
    return NULL;
  }
}
static GstBuffer *
gst_rtp_qcelp_depay_process (GstRTPBaseDepayload * depayload,
    GstRTPBuffer * rtp)
{
  GstRtpQCELPDepay *depay;
  GstBuffer *outbuf;
  GstClockTime timestamp;
  guint payload_len, offset, index;
  guint8 *payload;
  guint LLL, NNN;

  depay = GST_RTP_QCELP_DEPAY (depayload);

  payload_len = gst_rtp_buffer_get_payload_len (rtp);

  if (payload_len < 2)
    goto too_small;

  timestamp = GST_BUFFER_PTS (rtp->buffer);

  payload = gst_rtp_buffer_get_payload (rtp);

  /*  0 1 2 3 4 5 6 7
   * +-+-+-+-+-+-+-+-+
   * |RR | LLL | NNN |
   * +-+-+-+-+-+-+-+-+
   */
  /* RR = payload[0] >> 6; */
  LLL = (payload[0] & 0x38) >> 3;
  NNN = (payload[0] & 0x07);

  payload_len--;
  payload++;

  GST_DEBUG_OBJECT (depay, "LLL %u, NNN %u", LLL, NNN);

  if (LLL > 5)
    goto invalid_lll;

  if (NNN > LLL)
    goto invalid_nnn;

  if (LLL != 0) {
    /* we are interleaved */
    if (!depay->interleaved) {
      guint size;

      GST_DEBUG_OBJECT (depay, "starting interleaving group");
      /* bundling is not allowed to change in one interleave group */
      depay->bundling = count_packets (depay, payload, payload_len);
      GST_DEBUG_OBJECT (depay, "got bundling of %u", depay->bundling);
      /* we have one bundle where NNN goes from 0 to L, we don't store the index
       * 0 frames, so L+1 packets. Each packet has 'bundling - 1' packets */
      size = (depay->bundling - 1) * (LLL + 1);
      /* create the array to hold the packets */
      if (depay->packets == NULL)
        depay->packets = g_ptr_array_sized_new (size);
      GST_DEBUG_OBJECT (depay, "created packet array of size %u", size);
      g_ptr_array_set_size (depay->packets, size);
      /* we were previously not interleaved, figure out how much space we
       * need to deinterleave */
      depay->interleaved = TRUE;
    }
  } else {
    /* we are not interleaved */
    if (depay->interleaved) {
      GST_DEBUG_OBJECT (depay, "stopping interleaving");
      /* flush packets if we were previously interleaved */
      flush_packets (depay);
    }
    depay->bundling = 0;
  }

  index = 0;
  offset = 1;

  while (payload_len > 0) {
    gint frame_len;
    gboolean do_erasure;

    frame_len = get_frame_len (depay, payload[0]);
    GST_DEBUG_OBJECT (depay, "got frame len %d", frame_len);

    if (frame_len == 0)
      goto invalid_frame;

    if (frame_len < 0) {
      /* need to add an erasure frame but we can recover */
      frame_len = -frame_len;
      do_erasure = TRUE;
    } else {
      do_erasure = FALSE;
    }

    if (frame_len > payload_len)
      goto invalid_frame;

    if (do_erasure) {
      /* create erasure frame */
      outbuf = create_erasure_buffer (depay);
    } else {
      /* each frame goes into its buffer */
      outbuf = gst_rtp_buffer_get_payload_subbuffer (rtp, offset, frame_len);
    }

    GST_BUFFER_PTS (outbuf) = timestamp;
    GST_BUFFER_DURATION (outbuf) = FRAME_DURATION;

    gst_rtp_drop_meta (GST_ELEMENT_CAST (depayload), outbuf,
        g_quark_from_static_string (GST_META_TAG_AUDIO_STR));

    if (!depay->interleaved || index == 0) {
      /* not interleaved or first frame in packet, just push */
      gst_rtp_base_depayload_push (depayload, outbuf);

      if (timestamp != -1)
        timestamp += FRAME_DURATION;
    } else {
      /* put in interleave buffer */
      add_packet (depay, LLL, NNN, index, outbuf);

      if (timestamp != -1)
        timestamp += (FRAME_DURATION * (LLL + 1));
    }

    payload_len -= frame_len;
    payload += frame_len;
    offset += frame_len;
    index++;

    /* discard excess packets */
    if (depay->bundling > 0 && depay->bundling <= index)
      break;
  }
  while (index < depay->bundling) {
    GST_DEBUG_OBJECT (depay, "filling with erasure buffer");
    /* fill remainder with erasure packets */
    outbuf = create_erasure_buffer (depay);
    add_packet (depay, LLL, NNN, index, outbuf);
    index++;
  }
  if (depay->interleaved && LLL == NNN) {
    GST_DEBUG_OBJECT (depay, "interleave group ended, flushing");
    /* we have the complete interleave group, flush */
    flush_packets (depay);
  }

  return NULL;

  /* ERRORS */
too_small:
  {
    GST_ELEMENT_WARNING (depay, STREAM, DECODE,
        (NULL), ("QCELP RTP payload too small (%d)", payload_len));
    return NULL;
  }
invalid_lll:
  {
    GST_ELEMENT_WARNING (depay, STREAM, DECODE,
        (NULL), ("QCELP RTP invalid LLL received (%d)", LLL));
    return NULL;
  }
invalid_nnn:
  {
    GST_ELEMENT_WARNING (depay, STREAM, DECODE,
        (NULL), ("QCELP RTP invalid NNN received (%d)", NNN));
    return NULL;
  }
invalid_frame:
  {
    GST_ELEMENT_WARNING (depay, STREAM, DECODE,
        (NULL), ("QCELP RTP invalid frame received"));
    return NULL;
  }
}
static GstBuffer *
gst_rtp_dtmf_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
{

  GstRtpDTMFDepay *rtpdtmfdepay = NULL;
  GstBuffer *outbuf = NULL;
  gint payload_len;
  guint8 *payload = NULL;
  guint32 timestamp;
  GstRTPDTMFPayload dtmf_payload;
  gboolean marker;
  GstStructure *structure = NULL;
  GstMessage *dtmf_message = NULL;

  rtpdtmfdepay = GST_RTP_DTMF_DEPAY (depayload);

  if (!gst_rtp_buffer_validate (buf))
    goto bad_packet;

  payload_len = gst_rtp_buffer_get_payload_len (buf);
  payload = gst_rtp_buffer_get_payload (buf);

  if (payload_len != sizeof (GstRTPDTMFPayload))
    goto bad_packet;

  memcpy (&dtmf_payload, payload, sizeof (GstRTPDTMFPayload));

  if (dtmf_payload.event > MAX_EVENT)
    goto bad_packet;


  marker = gst_rtp_buffer_get_marker (buf);

  timestamp = gst_rtp_buffer_get_timestamp (buf);

  dtmf_payload.duration = g_ntohs (dtmf_payload.duration);

  /* clip to whole units of unit_time */
  if (rtpdtmfdepay->unit_time) {
    guint unit_time_clock =
        (rtpdtmfdepay->unit_time * depayload->clock_rate) / 1000;
    if (dtmf_payload.duration % unit_time_clock) {
      /* Make sure we don't overflow the duration */
      if (dtmf_payload.duration < G_MAXUINT16 - unit_time_clock)
        dtmf_payload.duration += unit_time_clock -
            (dtmf_payload.duration % unit_time_clock);
      else
        dtmf_payload.duration -= dtmf_payload.duration % unit_time_clock;
    }
  }

  /* clip to max duration */
  if (rtpdtmfdepay->max_duration) {
    guint max_duration_clock =
        (rtpdtmfdepay->max_duration * depayload->clock_rate) / 1000;

    if (max_duration_clock < G_MAXUINT16 &&
        dtmf_payload.duration > max_duration_clock)
      dtmf_payload.duration = max_duration_clock;
  }

  GST_DEBUG_OBJECT (depayload, "Received new RTP DTMF packet : "
      "marker=%d - timestamp=%u - event=%d - duration=%d",
      marker, timestamp, dtmf_payload.event, dtmf_payload.duration);

  GST_DEBUG_OBJECT (depayload,
      "Previous information : timestamp=%u - duration=%d",
      rtpdtmfdepay->previous_ts, rtpdtmfdepay->previous_duration);

  /* First packet */
  if (marker || rtpdtmfdepay->previous_ts != timestamp) {
    rtpdtmfdepay->sample = 0;
    rtpdtmfdepay->previous_ts = timestamp;
    rtpdtmfdepay->previous_duration = dtmf_payload.duration;
    rtpdtmfdepay->first_gst_ts = GST_BUFFER_TIMESTAMP (buf);

    structure = gst_structure_new ("dtmf-event",
        "number", G_TYPE_INT, dtmf_payload.event,
        "volume", G_TYPE_INT, dtmf_payload.volume,
        "type", G_TYPE_INT, 1, "method", G_TYPE_INT, 1, NULL);
    if (structure) {
      dtmf_message =
          gst_message_new_element (GST_OBJECT (depayload), structure);
      if (dtmf_message) {
        if (!gst_element_post_message (GST_ELEMENT (depayload), dtmf_message)) {
          GST_ERROR_OBJECT (depayload,
              "Unable to send dtmf-event message to bus");
        }
      } else {
        GST_ERROR_OBJECT (depayload, "Unable to create dtmf-event message");
      }
    } else {
      GST_ERROR_OBJECT (depayload, "Unable to create dtmf-event structure");
    }
  } else {
    guint16 duration = dtmf_payload.duration;
    dtmf_payload.duration -= rtpdtmfdepay->previous_duration;
    /* If late buffer, ignore */
    if (duration > rtpdtmfdepay->previous_duration)
      rtpdtmfdepay->previous_duration = duration;
  }

  GST_DEBUG_OBJECT (depayload, "new previous duration : %d - new duration : %d"
      " - diff  : %d - clock rate : %d - timestamp : %llu",
      rtpdtmfdepay->previous_duration, dtmf_payload.duration,
      (rtpdtmfdepay->previous_duration - dtmf_payload.duration),
      depayload->clock_rate, GST_BUFFER_TIMESTAMP (buf));

  /* If late or duplicate packet (like the redundant end packet). Ignore */
  if (dtmf_payload.duration > 0) {
    outbuf = gst_buffer_new ();
    gst_dtmf_src_generate_tone (rtpdtmfdepay, dtmf_payload, outbuf);


    GST_BUFFER_TIMESTAMP (outbuf) = rtpdtmfdepay->first_gst_ts +
        (rtpdtmfdepay->previous_duration - dtmf_payload.duration) *
        GST_SECOND / depayload->clock_rate;
    GST_BUFFER_OFFSET (outbuf) =
        (rtpdtmfdepay->previous_duration - dtmf_payload.duration) *
        GST_SECOND / depayload->clock_rate;
    GST_BUFFER_OFFSET_END (outbuf) = rtpdtmfdepay->previous_duration *
        GST_SECOND / depayload->clock_rate;

    GST_DEBUG_OBJECT (depayload, "timestamp : %llu - time %" GST_TIME_FORMAT,
        GST_BUFFER_TIMESTAMP (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));

  }

  return outbuf;


bad_packet:
  GST_ELEMENT_WARNING (rtpdtmfdepay, STREAM, DECODE,
      ("Packet did not validate"), (NULL));
  return NULL;
}
Beispiel #28
0
static gboolean
gst_rtp_g722_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
{
  GstStructure *structure;
  GstRtpG722Depay *rtpg722depay;
  gint clock_rate, payload, samplerate;
  gint channels;
  GstCaps *srccaps;
  gboolean res;
  const gchar *channel_order;
  const GstRTPChannelOrder *order;

  rtpg722depay = GST_RTP_G722_DEPAY (depayload);

  structure = gst_caps_get_structure (caps, 0);

  payload = 96;
  gst_structure_get_int (structure, "payload", &payload);
  switch (payload) {
    case GST_RTP_PAYLOAD_G722:
      channels = 1;
      clock_rate = 8000;
      samplerate = 16000;
      break;
    default:
      /* no fixed mapping, we need clock-rate */
      channels = 0;
      clock_rate = 0;
      samplerate = 0;
      break;
  }

  /* caps can overwrite defaults */
  clock_rate =
      gst_rtp_g722_depay_parse_int (structure, "clock-rate", clock_rate);
  if (clock_rate == 0)
    goto no_clockrate;

  if (clock_rate == 8000)
    samplerate = 16000;

  if (samplerate == 0)
    samplerate = clock_rate;

  channels =
      gst_rtp_g722_depay_parse_int (structure, "encoding-params", channels);
  if (channels == 0) {
    channels = gst_rtp_g722_depay_parse_int (structure, "channels", channels);
    if (channels == 0) {
      /* channels defaults to 1 otherwise */
      channels = 1;
    }
  }

  depayload->clock_rate = clock_rate;
  rtpg722depay->rate = samplerate;
  rtpg722depay->channels = channels;

  srccaps = gst_caps_new_simple ("audio/G722",
      "rate", G_TYPE_INT, samplerate, "channels", G_TYPE_INT, channels, NULL);

  /* add channel positions */
  channel_order = gst_structure_get_string (structure, "channel-order");

  order = gst_rtp_channels_get_by_order (channels, channel_order);
  if (order) {
    gst_audio_set_channel_positions (gst_caps_get_structure (srccaps, 0),
        order->pos);
  } else {
    GstAudioChannelPosition *pos;

    GST_ELEMENT_WARNING (rtpg722depay, STREAM, DECODE,
        (NULL), ("Unknown channel order '%s' for %d channels",
            GST_STR_NULL (channel_order), channels));
    /* create default NONE layout */
    pos = gst_rtp_channels_create_default (channels);
    gst_audio_set_channel_positions (gst_caps_get_structure (srccaps, 0), pos);
    g_free (pos);
  }

  res = gst_pad_set_caps (depayload->srcpad, srccaps);
  gst_caps_unref (srccaps);

  return res;

  /* ERRORS */
no_clockrate:
  {
    GST_ERROR_OBJECT (depayload, "no clock-rate specified");
    return FALSE;
  }
}
static GstFlowReturn
gst_rtp_dec_chain_rtp (GstPad * pad, GstObject * parent, GstBuffer * buffer)
{
    GstFlowReturn res;
    GstRTPDec *rtpdec;
    GstRTPDecSession *session;
    guint32 ssrc;
    guint8 pt;
    GstRTPBuffer rtp = { NULL, };

    rtpdec = GST_RTP_DEC (parent);

    GST_DEBUG_OBJECT (rtpdec, "got rtp packet");

    if (!gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp))
        goto bad_packet;

    ssrc = gst_rtp_buffer_get_ssrc (&rtp);
    pt = gst_rtp_buffer_get_payload_type (&rtp);
    gst_rtp_buffer_unmap (&rtp);

    GST_DEBUG_OBJECT (rtpdec, "SSRC %08x, PT %d", ssrc, pt);

    /* find session */
    session = gst_pad_get_element_private (pad);

    /* see if we have the pad */
    if (!session->active) {
        GstPadTemplate *templ;
        GstElementClass *klass;
        gchar *name;
        GstCaps *caps;
        GValue ret = { 0 };
        GValue args[3] = { {0}
            , {0}
            , {0}
        };

        GST_DEBUG_OBJECT (rtpdec, "creating stream");

        session->ssrc = ssrc;
        session->pt = pt;

        /* get pt map */
        g_value_init (&args[0], GST_TYPE_ELEMENT);
        g_value_set_object (&args[0], rtpdec);
        g_value_init (&args[1], G_TYPE_UINT);
        g_value_set_uint (&args[1], session->id);
        g_value_init (&args[2], G_TYPE_UINT);
        g_value_set_uint (&args[2], pt);

        g_value_init (&ret, GST_TYPE_CAPS);
        g_value_set_boxed (&ret, NULL);

        g_signal_emitv (args, gst_rtp_dec_signals[SIGNAL_REQUEST_PT_MAP], 0, &ret);

        caps = (GstCaps *) g_value_get_boxed (&ret);

        name = g_strdup_printf ("recv_rtp_src_%u_%u_%u", session->id, ssrc, pt);
        klass = GST_ELEMENT_GET_CLASS (rtpdec);
        templ = gst_element_class_get_pad_template (klass, "recv_rtp_src_%u_%u_%u");
        session->recv_rtp_src = gst_pad_new_from_template (templ, name);
        g_free (name);

        gst_pad_set_caps (session->recv_rtp_src, caps);

        gst_pad_set_element_private (session->recv_rtp_src, session);
        gst_pad_set_query_function (session->recv_rtp_src, gst_rtp_dec_query_src);
        gst_pad_set_active (session->recv_rtp_src, TRUE);
        gst_element_add_pad (GST_ELEMENT_CAST (rtpdec), session->recv_rtp_src);

        session->active = TRUE;
    }

    res = gst_pad_push (session->recv_rtp_src, buffer);

    return res;

bad_packet:
    {
        GST_ELEMENT_WARNING (rtpdec, STREAM, DECODE, (NULL),
                             ("RTP packet did not validate, dropping"));
        gst_buffer_unref (buffer);
        return GST_FLOW_OK;
    }
}
Beispiel #30
0
static int
set_hwparams (GstAlsaSink * alsa)
{
    guint rrate;
    gint err;
    snd_pcm_hw_params_t *params;
    guint period_time, buffer_time;

    snd_pcm_hw_params_malloc (&params);

    GST_DEBUG_OBJECT (alsa, "Negotiating to %d channels @ %d Hz (format = %s) "
                      "SPDIF (%d)", alsa->channels, alsa->rate,
                      snd_pcm_format_name (alsa->format), alsa->iec958);

    /* start with requested values, if we cannot configure alsa for those values,
     * we set these values to -1, which will leave the default alsa values */
    buffer_time = alsa->buffer_time;
    period_time = alsa->period_time;

retry:
    /* choose all parameters */
    CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config);
    /* set the interleaved read/write format */
    CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access),
           wrong_access);
    /* set the sample format */
    if (alsa->iec958) {
        /* Try to use big endian first else fallback to le and swap bytes */
        if (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format) < 0) {
            alsa->format = SND_PCM_FORMAT_S16_LE;
            alsa->need_swap = TRUE;
            GST_DEBUG_OBJECT (alsa, "falling back to little endian with swapping");
        } else {
            alsa->need_swap = FALSE;
        }
    }
    CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format),
           no_sample_format);
    /* set the count of channels */
    CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels),
           no_channels);
    /* set the stream rate */
    rrate = alsa->rate;
    CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL),
           no_rate);

#ifndef GST_DISABLE_GST_DEBUG
    /* get and dump some limits */
    {
        guint min, max;

        snd_pcm_hw_params_get_buffer_time_min (params, &min, NULL);
        snd_pcm_hw_params_get_buffer_time_max (params, &max, NULL);

        GST_DEBUG_OBJECT (alsa, "buffer time %u, min %u, max %u",
                          alsa->buffer_time, min, max);

        snd_pcm_hw_params_get_period_time_min (params, &min, NULL);
        snd_pcm_hw_params_get_period_time_max (params, &max, NULL);

        GST_DEBUG_OBJECT (alsa, "period time %u, min %u, max %u",
                          alsa->period_time, min, max);

        snd_pcm_hw_params_get_periods_min (params, &min, NULL);
        snd_pcm_hw_params_get_periods_max (params, &max, NULL);

        GST_DEBUG_OBJECT (alsa, "periods min %u, max %u", min, max);
    }
#endif

    /* now try to configure the buffer time and period time, if one
     * of those fail, we fall back to the defaults and emit a warning. */
    if (buffer_time != -1 && !alsa->iec958) {
        /* set the buffer time */
        if ((err = snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
                   &buffer_time, NULL)) < 0) {
            GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
                                 ("Unable to set buffer time %i for playback: %s",
                                  buffer_time, snd_strerror (err)));
            /* disable buffer_time the next round */
            buffer_time = -1;
            goto retry;
        }
        GST_DEBUG_OBJECT (alsa, "buffer time %u", buffer_time);
    }
    if (period_time != -1 && !alsa->iec958) {
        /* set the period time */
        if ((err = snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
                   &period_time, NULL)) < 0) {
            GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
                                 ("Unable to set period time %i for playback: %s",
                                  period_time, snd_strerror (err)));
            /* disable period_time the next round */
            period_time = -1;
            goto retry;
        }
        GST_DEBUG_OBJECT (alsa, "period time %u", period_time);
    }

    /* Set buffer size and period size manually for SPDIF */
    if (G_UNLIKELY (alsa->iec958)) {
        snd_pcm_uframes_t buffer_size = SPDIF_BUFFER_SIZE;
        snd_pcm_uframes_t period_size = SPDIF_PERIOD_SIZE;

        CHECK (snd_pcm_hw_params_set_buffer_size_near (alsa->handle, params,
                &buffer_size), buffer_size);
        CHECK (snd_pcm_hw_params_set_period_size_near (alsa->handle, params,
                &period_size, NULL), period_size);
    }

    /* write the parameters to device */
    CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params);

    /* now get the configured values */
    CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
           buffer_size);
    CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, NULL),
           period_size);

    GST_DEBUG_OBJECT (alsa, "buffer size %lu, period size %lu", alsa->buffer_size,
                      alsa->period_size);

    snd_pcm_hw_params_free (params);
    return 0;

    /* ERRORS */
no_config:
    {
        GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
                           ("Broken configuration for playback: no configurations available: %s",
                            snd_strerror (err)));
        snd_pcm_hw_params_free (params);
        return err;
    }
wrong_access:
    {
        GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
                           ("Access type not available for playback: %s", snd_strerror (err)));
        snd_pcm_hw_params_free (params);
        return err;
    }
no_sample_format:
    {
        GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
                           ("Sample format not available for playback: %s", snd_strerror (err)));
        snd_pcm_hw_params_free (params);
        return err;
    }
no_channels:
    {
        gchar *msg = NULL;

        if ((alsa->channels) == 1)
            msg = g_strdup (_("Could not open device for playback in mono mode."));
        if ((alsa->channels) == 2)
            msg = g_strdup (_("Could not open device for playback in stereo mode."));
        if ((alsa->channels) > 2)
            msg =
                g_strdup_printf (_
                                 ("Could not open device for playback in %d-channel mode."),
                                 alsa->channels);
        GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, ("%s", msg),
                           ("%s", snd_strerror (err)));
        g_free (msg);
        snd_pcm_hw_params_free (params);
        return err;
    }
no_rate:
    {
        GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
                           ("Rate %iHz not available for playback: %s",
                            alsa->rate, snd_strerror (err)));
        return err;
    }
buffer_size:
    {
        GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
                           ("Unable to get buffer size for playback: %s", snd_strerror (err)));
        snd_pcm_hw_params_free (params);
        return err;
    }
period_size:
    {
        GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
                           ("Unable to get period size for playback: %s", snd_strerror (err)));
        snd_pcm_hw_params_free (params);
        return err;
    }
set_hw_params:
    {
        GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
                           ("Unable to set hw params for playback: %s", snd_strerror (err)));
        snd_pcm_hw_params_free (params);
        return err;
    }
}