Beispiel #1
0
static gboolean
gst_vdp_mpeg_dec_src_query (GstPad * pad, GstQuery * query)
{
    GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (gst_pad_get_parent (pad));
    gboolean res;

    switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_POSITION:
    {
        GstFormat format;

        if ((res = gst_pad_query_default (pad, query)))
            goto done;

        gst_query_parse_position (query, &format, NULL);
        if (format == GST_FORMAT_TIME &&
                GST_CLOCK_TIME_IS_VALID (mpeg_dec->next_timestamp)) {
            gst_query_set_position (query, GST_FORMAT_TIME,
                                    mpeg_dec->next_timestamp);
            res = TRUE;
        }
        break;
    }

    case GST_QUERY_DURATION:
    {
        GstFormat format;

        if ((res = gst_pad_query_default (pad, query)))
            goto done;

        gst_query_parse_duration (query, &format, NULL);
        if (format == GST_FORMAT_TIME) {
            gint64 bytes;

            format = GST_FORMAT_BYTES;
            if (gst_pad_query_duration (pad, &format, &bytes)
                    && format == GST_FORMAT_BYTES) {
                gint64 duration;

                if (gst_vdp_mpeg_dec_convert (mpeg_dec, GST_FORMAT_BYTES,
                                              bytes, GST_FORMAT_TIME, &duration)) {
                    GST_DEBUG ("duration: %" GST_TIME_FORMAT, GST_TIME_ARGS (duration));
                    gst_query_set_duration (query, GST_FORMAT_TIME, duration);
                    res = TRUE;
                }
            }
        }
        break;
    }

    default:
        res = gst_pad_query_default (pad, query);
    }

done:
    gst_object_unref (mpeg_dec);

    return res;
}
Beispiel #2
0
static gboolean
gst_timidity_get_upstream_size (GstTimidity * timidity, gint64 * size)
{
  GstFormat format = GST_FORMAT_BYTES;
  gboolean res = FALSE;
  GstPad *peer = gst_pad_get_peer (timidity->sinkpad);

  if (peer != NULL)
    res = gst_pad_query_duration (peer, &format, size) && *size >= 0;

  gst_object_unref (peer);
  return res;
}
Beispiel #3
0
static int64_t
gst_ffmpegdata_seek (URLContext * h, int64_t pos, int whence)
{
    GstProtocolInfo *info;
    guint64 newpos = 0, oldpos;

    GST_DEBUG ("Seeking to %" G_GINT64_FORMAT ", whence=%d",
               (gint64) pos, whence);

    info = (GstProtocolInfo *) h->priv_data;

    /* TODO : if we are push-based, we need to return sensible info */

    switch (h->flags) {
    case URL_RDONLY:
    {
        /* sinkpad */
        switch (whence) {
        case SEEK_SET:
            newpos = (guint64) pos;
            break;
        case SEEK_CUR:
            newpos = info->offset + pos;
            break;
        case SEEK_END:
        case AVSEEK_SIZE:
            /* ffmpeg wants to know the current end position in bytes ! */
        {
            gint64 duration;

            GST_DEBUG ("Seek end");

            if (gst_pad_is_linked (info->pad))
                if (gst_pad_query_duration (GST_PAD_PEER (info->pad),
                                            GST_FORMAT_BYTES, &duration))
                    newpos = ((guint64) duration) + pos;
        }
        break;
        default:
            g_assert (0);
            break;
        }
        /* FIXME : implement case for push-based behaviour */
        if (whence != AVSEEK_SIZE)
            info->offset = newpos;
    }
    break;
    case URL_WRONLY:
    {
        GstSegment segment;

        oldpos = info->offset;

        /* srcpad */
        switch (whence) {
        case SEEK_SET:
        {
            info->offset = (guint64) pos;
            break;
        }
        case SEEK_CUR:
            info->offset += pos;
            break;
        default:
            break;
        }
        newpos = info->offset;

        if (newpos != oldpos) {
            gst_segment_init (&segment, GST_FORMAT_BYTES);
            segment.start = newpos;
            segment.time = newpos;
            gst_pad_push_event (info->pad, gst_event_new_segment (&segment));
        }
        break;
    }
    default:
        g_assert (0);
        break;
    }

    GST_DEBUG ("Now at offset %" G_GUINT64_FORMAT " (returning %" G_GUINT64_FORMAT
               ")", info->offset, newpos);
    return newpos;
}
static void
gst_type_find_element_loop (GstPad * pad)
{
  GstTypeFindElement *typefind;
  GstFlowReturn ret = GST_FLOW_OK;

  typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));

  if (typefind->need_stream_start) {
    gchar *stream_id;
    GstEvent *event;

    stream_id = gst_pad_create_stream_id (typefind->src,
        GST_ELEMENT_CAST (typefind), NULL);

    GST_DEBUG_OBJECT (typefind, "Pushing STREAM_START");
    event = gst_event_new_stream_start (stream_id);
    gst_event_set_group_id (event, gst_util_group_id_next ());
    gst_pad_push_event (typefind->src, event);

    typefind->need_stream_start = FALSE;
    g_free (stream_id);
  }

  if (typefind->mode == MODE_TYPEFIND) {
    GstPad *peer = NULL;
    GstCaps *found_caps = NULL;
    GstTypeFindProbability probability = GST_TYPE_FIND_NONE;

    GST_DEBUG_OBJECT (typefind, "find type in pull mode");

    GST_OBJECT_LOCK (typefind);
    if (typefind->force_caps) {
      found_caps = gst_caps_ref (typefind->force_caps);
      probability = GST_TYPE_FIND_MAXIMUM;
    }
    GST_OBJECT_UNLOCK (typefind);

    if (!found_caps) {
      peer = gst_pad_get_peer (pad);
      if (peer) {
        gint64 size;
        gchar *ext;

        if (!gst_pad_query_duration (peer, GST_FORMAT_BYTES, &size)) {
          GST_WARNING_OBJECT (typefind, "Could not query upstream length!");
          gst_object_unref (peer);

          ret = GST_FLOW_ERROR;
          goto pause;
        }

        /* the size if 0, we cannot continue */
        if (size == 0) {
          /* keep message in sync with message in sink event handler */
          GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
              (_("Stream contains no data.")), ("Can't typefind empty stream"));
          gst_object_unref (peer);
          ret = GST_FLOW_ERROR;
          goto pause;
        }
        ext = gst_type_find_get_extension (typefind, pad);

        found_caps =
            gst_type_find_helper_get_range (GST_OBJECT_CAST (peer),
            GST_OBJECT_PARENT (peer),
            (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (peer)),
            (guint64) size, ext, &probability);
        g_free (ext);

        GST_DEBUG ("Found caps %" GST_PTR_FORMAT, found_caps);

        gst_object_unref (peer);
      }
    }

    if (!found_caps || probability < typefind->min_probability) {
      GST_DEBUG ("Trying to guess using extension");
      gst_caps_replace (&found_caps, NULL);
      found_caps =
          gst_type_find_guess_by_extension (typefind, pad, &probability);
    }

    if (!found_caps || probability < typefind->min_probability) {
      GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
      gst_caps_replace (&found_caps, NULL);
      ret = GST_FLOW_ERROR;
      goto pause;
    }

    GST_DEBUG ("Emiting found caps %" GST_PTR_FORMAT, found_caps);
    gst_type_find_element_emit_have_type (typefind, probability, found_caps);
    typefind->mode = MODE_NORMAL;
    gst_caps_unref (found_caps);
  } else if (typefind->mode == MODE_NORMAL) {
    GstBuffer *outbuf = NULL;

    if (typefind->need_segment) {
      typefind->need_segment = FALSE;
      gst_pad_push_event (typefind->src,
          gst_event_new_segment (&typefind->segment));
    }

    /* Pull 4k blocks and send downstream */
    ret = gst_pad_pull_range (typefind->sink, typefind->offset, 4096, &outbuf);
    if (ret != GST_FLOW_OK)
      goto pause;

    typefind->offset += gst_buffer_get_size (outbuf);

    ret = gst_pad_push (typefind->src, outbuf);
    if (ret != GST_FLOW_OK)
      goto pause;
  } else {
    /* Error out */
    ret = GST_FLOW_ERROR;
    goto pause;
  }

  return;

pause:
  {
    const gchar *reason = gst_flow_get_name (ret);
    gboolean push_eos = FALSE;

    GST_LOG_OBJECT (typefind, "pausing task, reason %s", reason);
    gst_pad_pause_task (typefind->sink);

    if (ret == GST_FLOW_EOS) {
      /* perform EOS logic */

      if (typefind->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
        gint64 stop;

        /* for segment playback we need to post when (in stream time)
         * we stopped, this is either stop (when set) or the duration. */
        if ((stop = typefind->segment.stop) == -1)
          stop = typefind->offset;

        GST_LOG_OBJECT (typefind, "Sending segment done, at end of segment");
        gst_element_post_message (GST_ELEMENT (typefind),
            gst_message_new_segment_done (GST_OBJECT (typefind),
                GST_FORMAT_BYTES, stop));
        gst_pad_push_event (typefind->src,
            gst_event_new_segment_done (GST_FORMAT_BYTES, stop));
      } else {
        push_eos = TRUE;
      }
    } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
      /* for fatal errors we post an error message */
      GST_ELEMENT_ERROR (typefind, STREAM, FAILED, (NULL),
          ("stream stopped, reason %s", reason));
      push_eos = TRUE;
    }
    if (push_eos) {
      /* send EOS, and prevent hanging if no streams yet */
      GST_LOG_OBJECT (typefind, "Sending EOS, at end of stream");
      gst_pad_push_event (typefind->src, gst_event_new_eos ());
    }
    return;
  }
}
static gboolean
xing_mp3_encoder_src_query(GstPad * pad, GstQuery * query)
{
    gboolean res = TRUE;
    XingMp3Encoder *encoder;
    GstPad *peerpad;

    encoder = XING_MP3_ENCODER(gst_pad_get_parent(pad));
    peerpad = gst_pad_get_peer(GST_PAD(encoder->sinkpad));
  
    switch(GST_QUERY_TYPE(query)) {
        case GST_QUERY_DURATION: {
            GstFormat fmt, req_fmt;
            gint64 dur, val;

            gst_query_parse_duration(query, &req_fmt, NULL);
            if((res = gst_pad_query_duration(peerpad, &req_fmt, &val))) {
                gst_query_set_duration(query, req_fmt, val);
                break;
            }

            fmt = GST_FORMAT_TIME;
            if(!(res = gst_pad_query_duration (peerpad, &fmt, &dur))) {
                break;
            }
            
            if((res = gst_pad_query_convert(peerpad, fmt, dur, &req_fmt, &val))) {
                gst_query_set_duration(query, req_fmt, val);
            }
            break;
        }

        case GST_QUERY_POSITION: {
            GstFormat fmt, req_fmt;
            gint64 pos, val;

            gst_query_parse_position(query, &req_fmt, NULL);
            if((res = gst_pad_query_position(peerpad, &req_fmt, &val))) {
                gst_query_set_position (query, req_fmt, val);
                break;
            }

            fmt = GST_FORMAT_TIME;
            if(!(res = gst_pad_query_position(peerpad, &fmt, &pos))) {
                break;
            }
            
            if((res = gst_pad_query_convert(peerpad, fmt, pos, &req_fmt, &val))) {
                gst_query_set_position(query, req_fmt, val);
            }
            break;
        }
        
        case GST_QUERY_CONVERT: {
            GstFormat src_fmt, dest_fmt;
            gint64 src_val, dest_val;

            gst_query_parse_convert(query, &src_fmt, &src_val, &dest_fmt, &dest_val);
            if(!(res = xing_mp3_encoder_convert_src(pad, src_fmt, src_val, &dest_fmt, &dest_val))) {
                gst_object_unref(peerpad);
                gst_object_unref(encoder);
            }
            
            gst_query_set_convert(query, src_fmt, src_val, dest_fmt, dest_val);
            break;
        }
        
        default:
            res = gst_pad_query_default(pad, query);
            break;
    }

    return res;
}
Beispiel #6
0
static gboolean
gst_vorbis_enc_src_query (GstPad * pad, GstQuery * query)
{
  gboolean res = TRUE;
  GstVorbisEnc *vorbisenc;
  GstPad *peerpad;

  vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
  peerpad = gst_pad_get_peer (GST_PAD (vorbisenc->sinkpad));

  switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_POSITION:
    {
      GstFormat fmt, req_fmt;
      gint64 pos, val;

      gst_query_parse_position (query, &req_fmt, NULL);
      if ((res = gst_pad_query_position (peerpad, &req_fmt, &val))) {
        gst_query_set_position (query, req_fmt, val);
        break;
      }

      fmt = GST_FORMAT_TIME;
      if (!(res = gst_pad_query_position (peerpad, &fmt, &pos)))
        break;

      if ((res = gst_pad_query_convert (peerpad, fmt, pos, &req_fmt, &val))) {
        gst_query_set_position (query, req_fmt, val);
      }
      break;
    }
    case GST_QUERY_DURATION:
    {
      GstFormat fmt, req_fmt;
      gint64 dur, val;

      gst_query_parse_duration (query, &req_fmt, NULL);
      if ((res = gst_pad_query_duration (peerpad, &req_fmt, &val))) {
        gst_query_set_duration (query, req_fmt, val);
        break;
      }

      fmt = GST_FORMAT_TIME;
      if (!(res = gst_pad_query_duration (peerpad, &fmt, &dur)))
        break;

      if ((res = gst_pad_query_convert (peerpad, fmt, dur, &req_fmt, &val))) {
        gst_query_set_duration (query, req_fmt, val);
      }
      break;
    }
    case GST_QUERY_CONVERT:
    {
      GstFormat src_fmt, dest_fmt;
      gint64 src_val, dest_val;

      gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
      if (!(res =
              gst_vorbis_enc_convert_src (pad, src_fmt, src_val, &dest_fmt,
                  &dest_val)))
        goto error;
      gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
      break;
    }
    default:
      res = gst_pad_query_default (pad, query);
      break;
  }

error:
  gst_object_unref (peerpad);
  gst_object_unref (vorbisenc);
  return res;
}
static gboolean
gst_wavpack_parse_src_query (GstPad * pad, GstQuery * query)
{
  GstWavpackParse *parse = GST_WAVPACK_PARSE (gst_pad_get_parent (pad));

  GstFormat format;

  gboolean ret = FALSE;

  switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_POSITION:{
      gint64 cur;

      guint rate;

      GST_OBJECT_LOCK (parse);
      cur = parse->segment.last_stop;
      rate = parse->samplerate;
      GST_OBJECT_UNLOCK (parse);

      if (rate == 0) {
        GST_DEBUG_OBJECT (parse, "haven't read header yet");
        break;
      }

      gst_query_parse_position (query, &format, NULL);

      switch (format) {
        case GST_FORMAT_TIME:
          cur = gst_util_uint64_scale_int (cur, GST_SECOND, rate);
          gst_query_set_position (query, GST_FORMAT_TIME, cur);
          ret = TRUE;
          break;
        case GST_FORMAT_DEFAULT:
          gst_query_set_position (query, GST_FORMAT_DEFAULT, cur);
          ret = TRUE;
          break;
        default:
          GST_DEBUG_OBJECT (parse, "cannot handle position query in "
              "%s format. Forwarding upstream.", gst_format_get_name (format));
          ret = gst_pad_query_default (pad, query);
          break;
      }
      break;
    }
    case GST_QUERY_DURATION:{
      gint64 len;

      guint rate;

      GST_OBJECT_LOCK (parse);
      rate = parse->samplerate;
      len = parse->total_samples;
      GST_OBJECT_UNLOCK (parse);

      if (rate == 0) {
        GST_DEBUG_OBJECT (parse, "haven't read header yet");
        break;
      }

      gst_query_parse_duration (query, &format, NULL);

      switch (format) {
        case GST_FORMAT_TIME:
          if (len != G_GINT64_CONSTANT (-1))
            len = gst_util_uint64_scale_int (len, GST_SECOND, rate);
          gst_query_set_duration (query, GST_FORMAT_TIME, len);
          ret = TRUE;
          break;
        case GST_FORMAT_DEFAULT:
          gst_query_set_duration (query, GST_FORMAT_DEFAULT, len);
          ret = TRUE;
          break;
        default:
          GST_DEBUG_OBJECT (parse, "cannot handle duration query in "
              "%s format. Forwarding upstream.", gst_format_get_name (format));
          ret = gst_pad_query_default (pad, query);
          break;
      }
      break;
    }
    case GST_QUERY_SEEKING:{
      gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
      if (format == GST_FORMAT_TIME || format == GST_FORMAT_DEFAULT) {
        gboolean seekable;

        gint64 duration = -1;

        /* only fails if we didn't read the headers yet and can't say
         * anything about our seeking capabilities */
        if (!gst_pad_query_duration (pad, &format, &duration))
          break;

        /* can't seek in streaming mode yet */
        GST_OBJECT_LOCK (parse);
        seekable = (parse->adapter == NULL);
        GST_OBJECT_UNLOCK (parse);

        gst_query_set_seeking (query, format, seekable, 0, duration);
        ret = TRUE;
      }
      break;
    }
    default:{
      ret = gst_pad_query_default (pad, query);
      break;
    }
  }

  gst_object_unref (parse);
  return ret;

}
Beispiel #8
0
// ----------------------------------------------------------------------------
// Handle the "pad-added" message
void
GStreamerImportFileHandle::OnPadAdded(GstPad *pad)
{
   // Retrieve the stream caps...skip stream if unavailable
   GstCaps *caps = gst_pad_get_current_caps(pad);
   if (!caps)
   {
      WARN(mPipeline, ("OnPadAdded: unable to retrieve stream caps"));
      return;
   }

   // Get the caps structure...no need to release
   GstStructure *str = gst_caps_get_structure(caps, 0);
   if (!str)
   {
      WARN(mPipeline, ("OnPadAdded: unable to retrieve caps structure"));
      gst_caps_unref(caps);
      return;
   }

   // Only accept audio streams...no need to release
   const gchar *name = gst_structure_get_name(str);
   if (!g_strrstr(name, "audio"))
   {
      WARN(mPipeline, ("OnPadAdded: bypassing '%s' stream", name));
      gst_caps_unref(caps);
      return;
   }

   // Allocate a new stream context
   GStreamContext *c = g_new0(GStreamContext, 1);
   if (!c)
   {
      WARN(mPipeline, ("OnPadAdded: unable to allocate stream context"));
      gst_caps_unref(caps);
      return;
   }

   // Set initial state
   c->mUse = true;

   // Always add it to the context list to keep the number of contexts
   // in sync with the number of streams
   g_mutex_lock(&mStreamsLock);
   g_ptr_array_add(mStreams, c);
   g_mutex_unlock(&mStreamsLock);

   // Need pointer to context during pad removal (pad-remove signal)
   SETCTX(pad, c);

   // Save the stream's start time and duration
   gst_pad_query_position(pad, GST_FORMAT_TIME, &c->mPosition);
   gst_pad_query_duration(pad, GST_FORMAT_TIME, &c->mDuration);

   // Retrieve the number of channels and validate
   gint channels = -1;
   gst_structure_get_int(str, "channels", &channels);
   if (channels <= 0)
   {
      WARN(mPipeline, ("OnPadAdded: channel count is invalid %d", channels));
      gst_caps_unref(caps);
      return;
   }
   c->mNumChannels = channels;

   // Retrieve the sample rate and validate
   gint rate = -1;
   gst_structure_get_int(str, "rate", &rate);
   if (rate <= 0)
   {
      WARN(mPipeline, ("OnPadAdded: sample rate is invalid %d", rate));
      gst_caps_unref(caps);
      return;
   }
   c->mSampleRate = (double) rate;

   c->mType = g_strdup(name);
   if (c->mType == NULL)
   {
      WARN(mPipeline, ("OnPadAdded: unable to allocate audio type"));
      gst_caps_unref(caps);
      return;
   }

   // Done with capabilities
   gst_caps_unref(caps);

   // Create audioconvert element
   c->mConv = gst_element_factory_make("audioconvert", NULL);
   if (!c->mConv)
   {
      WARN(mPipeline, ("OnPadAdded: failed to create audioconvert element"));
      return;
   }

   // Create appsink element
   c->mSink = gst_element_factory_make("appsink", NULL);
   if (!c->mSink)
   {
      WARN(mPipeline, ("OnPadAdded: failed to create appsink element"));
      return;
   }
   SETCTX(c->mSink, c);

   // Set the appsink callbacks and add the context pointer
   gst_app_sink_set_callbacks(GST_APP_SINK(c->mSink), &AppSinkCallbacks, this, NULL);

   // Set the capabilities that we desire
   caps = gst_static_caps_get(&supportedCaps);
   if (!caps)
   {
      WARN(mPipeline, ("OnPadAdded: failed to create static caps"));
      return;
   }
   gst_app_sink_set_caps(GST_APP_SINK(c->mSink), caps);
   gst_caps_unref(caps);

   // Do not sync to the clock...process as quickly as possible
   gst_base_sink_set_sync(GST_BASE_SINK(c->mSink), FALSE);

   // Don't drop buffers...allow queue to build unfettered
   gst_app_sink_set_drop(GST_APP_SINK(c->mSink), FALSE);

   // Add both elements to the pipeline
   gst_bin_add_many(GST_BIN(mPipeline), c->mConv, c->mSink, NULL);

   // Link them together
   if (!gst_element_link(c->mConv, c->mSink))
   {
      WARN(mPipeline, ("OnPadAdded: failed to link autioconvert and appsink"));
      return;
   }

   // Link the audiconvert sink pad to the src pad
   GstPadLinkReturn ret = GST_PAD_LINK_OK;
   GstPad *convsink = gst_element_get_static_pad(c->mConv, "sink");
   if (convsink)
   {
      ret = gst_pad_link(pad, convsink);
      gst_object_unref(convsink);
   }
   if (!convsink || ret != GST_PAD_LINK_OK)
   {
      WARN(mPipeline, ("OnPadAdded: failed to link uridecodebin to audioconvert - %d", ret));
      return;
   }

   // Synchronize audioconvert state with parent
   if (!gst_element_sync_state_with_parent(c->mConv))
   {
      WARN(mPipeline, ("OnPadAdded: unable to sync audioconvert state"));
      return;
   }

   // Synchronize appsink state with parent
   if (!gst_element_sync_state_with_parent(c->mSink))
   {
      WARN(mPipeline, ("OnPadAdded: unable to sync appaink state"));
      return;
   }

   return;
}
static gboolean
gst_type_find_element_activate (GstPad * pad)
{
  GstTypeFindProbability probability = 0;
  GstCaps *found_caps = NULL;
  GstTypeFindElement *typefind;

  typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad));

  /* if we have force caps, use those */
  if (typefind->force_caps) {
    found_caps = gst_caps_ref (typefind->force_caps);
    probability = GST_TYPE_FIND_MAXIMUM;
    goto done;
  }

  /* 1. try to activate in pull mode. if not, switch to push and succeed.
     2. try to pull type find.
     3. deactivate pull mode.
     4. src pad might have been activated push by the state change. deactivate.
     5. if we didn't find any caps, try getting the uri extension by doing an uri
     query.
     6. if we didn't find any caps, fail.
     7. emit have-type; maybe the app connected the source pad to something.
     8. if the sink pad is activated, we are in pull mode. succeed.
     otherwise activate both pads in push mode and succeed.
   */

  /* 1 */
  if (!gst_pad_check_pull_range (pad) || !gst_pad_activate_pull (pad, TRUE)) {
    start_typefinding (typefind);
    return gst_pad_activate_push (pad, TRUE);
  }

  /* 2 */
  {
    GstPad *peer;

    peer = gst_pad_get_peer (pad);
    if (peer) {
      gint64 size;
      GstFormat format = GST_FORMAT_BYTES;

      if (!gst_pad_query_duration (peer, &format, &size)) {
        GST_WARNING_OBJECT (typefind, "Could not query upstream length!");
        gst_object_unref (peer);
        return FALSE;
      }

      /* the size if 0, we cannot continue */
      if (size == 0) {
        /* keep message in sync with message in sink event handler */
        GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
            (_("Stream contains no data.")), ("Can't typefind empty stream"));
        gst_object_unref (peer);
        return FALSE;
      }

      found_caps = gst_type_find_helper_get_range (GST_OBJECT_CAST (peer),
          (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (peer)),
          (guint64) size, &probability);

      gst_object_unref (peer);
    }
  }

  /* 3 */
  gst_pad_activate_pull (pad, FALSE);

  /* 4 */
  gst_pad_activate_push (typefind->src, FALSE);

  /* 5 */
  if (!found_caps || probability < typefind->min_probability) {
    found_caps = gst_type_find_guess_by_extension (typefind, pad, &probability);
  }

  /* 6 */
  if (!found_caps || probability < typefind->min_probability) {
    GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
    gst_caps_replace (&found_caps, NULL);
    return FALSE;
  }

done:
  /* 7 */
  g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
      0, probability, found_caps);
  gst_caps_unref (found_caps);
  typefind->mode = MODE_NORMAL;

  /* 8 */
  if (gst_pad_is_active (pad))
    return TRUE;
  else {
    gboolean ret;

    ret = gst_pad_activate_push (typefind->src, TRUE);
    ret &= gst_pad_activate_push (pad, TRUE);
    return ret;
  }
}
Beispiel #10
0
static void
gst_cdxa_parse_loop (GstPad * sinkpad)
{
  GstFlowReturn flow_ret;
  GstCDXAParse *cdxa;
  GstBuffer *buf = NULL;
  gint sync_offset = -1;

  cdxa = GST_CDXA_PARSE (GST_PAD_PARENT (sinkpad));

  if (cdxa->datasize <= 0) {
    GstFormat format = GST_FORMAT_BYTES;
    GstPad *peer;

    if ((peer = gst_pad_get_peer (sinkpad))) {
      if (!gst_pad_query_duration (peer, &format, &cdxa->datasize)) {
        GST_DEBUG_OBJECT (cdxa, "Failed to query upstream size!");
        gst_object_unref (peer);
        goto pause;
      }
      gst_object_unref (peer);
    }
    GST_DEBUG_OBJECT (cdxa, "Upstream size: %" G_GINT64_FORMAT, cdxa->datasize);
  }

  do {
    guint req;

    req = 8 + GST_CDXA_SECTOR_SIZE;     /* riff chunk header = 8 bytes */

    buf = NULL;
    flow_ret = gst_pad_pull_range (cdxa->sinkpad, cdxa->offset, req, &buf);

    if (flow_ret != GST_FLOW_OK) {
      GST_DEBUG_OBJECT (cdxa, "Pull flow: %s", gst_flow_get_name (flow_ret));
      goto pause;
    }

    if (GST_BUFFER_SIZE (buf) < req) {
      GST_DEBUG_OBJECT (cdxa, "Short read, only got %u/%u bytes",
          GST_BUFFER_SIZE (buf), req);
      goto eos;
    }

    sync_offset = gst_cdxa_parse_sync (buf);
    gst_buffer_unref (buf);
    buf = NULL;

    if (sync_offset >= 0)
      break;

    cdxa->offset += req;
    cdxa->bytes_skipped += req;
  } while (1);

  cdxa->offset += sync_offset;
  cdxa->bytes_skipped += sync_offset;

  /* first sync frame? */
  if (cdxa->datastart < 0) {
    GST_LOG_OBJECT (cdxa, "datastart=0x%" G_GINT64_MODIFIER "x", cdxa->offset);
    cdxa->datastart = cdxa->offset;
    cdxa->bytes_skipped = 0;
    cdxa->bytes_sent = 0;
  }

  GST_DEBUG_OBJECT (cdxa, "pulling buffer at offset 0x%" G_GINT64_MODIFIER "x",
      cdxa->offset);

  buf = NULL;
  flow_ret = gst_pad_pull_range (cdxa->sinkpad, cdxa->offset,
      GST_CDXA_SECTOR_SIZE, &buf);

  if (flow_ret != GST_FLOW_OK) {
    GST_DEBUG_OBJECT (cdxa, "Flow: %s", gst_flow_get_name (flow_ret));
    goto pause;
  }

  if (GST_BUFFER_SIZE (buf) < GST_CDXA_SECTOR_SIZE) {
    GST_DEBUG_OBJECT (cdxa, "Short read, only got %u/%u bytes",
        GST_BUFFER_SIZE (buf), GST_CDXA_SECTOR_SIZE);
    goto eos;
  }

  buf = gst_cdxa_parse_strip (buf);

  GST_DEBUG_OBJECT (cdxa, "pushing buffer %p", buf);
  gst_buffer_set_caps (buf, GST_PAD_CAPS (cdxa->srcpad));

  cdxa->offset += GST_BUFFER_SIZE (buf);
  cdxa->bytes_sent += GST_BUFFER_SIZE (buf);

  flow_ret = gst_pad_push (cdxa->srcpad, buf);
  if (flow_ret != GST_FLOW_OK) {
    GST_DEBUG_OBJECT (cdxa, "Push flow: %s", gst_flow_get_name (flow_ret));
    goto pause;
  }

  return;

eos:
  {
    GST_DEBUG_OBJECT (cdxa, "Sending EOS");
    if (buf)
      gst_buffer_unref (buf);
    buf = NULL;
    gst_pad_push_event (cdxa->srcpad, gst_event_new_eos ());
    /* fallthrough */
  }
pause:
  {
    GST_DEBUG_OBJECT (cdxa, "Pausing");
    gst_pad_pause_task (cdxa->sinkpad);
    return;
  }
}
Beispiel #11
0
static offset_t
gst_ffmpegdata_seek (URLContext * h, offset_t pos, int whence)
{
  GstProtocolInfo *info;
  guint64 newpos;

  GST_DEBUG ("Seeking to %" G_GINT64_FORMAT ", whence=%d", pos, whence);

  info = (GstProtocolInfo *) h->priv_data;

  /* TODO : if we are push-based, we need to return sensible info */

  switch (h->flags) {
    case URL_RDONLY:
    {
      /* sinkpad */
      switch (whence) {
        case SEEK_SET:
          info->offset = (guint64) pos;
          break;
        case SEEK_CUR:
          info->offset += pos;
          break;
        case SEEK_END:
          /* ffmpeg wants to know the current end position in bytes ! */
        {
          GstFormat format = GST_FORMAT_BYTES;
          gint64 duration;

          if (gst_pad_is_linked (info->pad))
            if (gst_pad_query_duration (GST_PAD_PEER (info->pad), &format,
                    &duration))
              info->offset = ((guint64) duration) + pos;
        }
          break;
        default:
          break;
      }
      /* FIXME : implement case for push-based behaviour */
      newpos = info->offset;
    }
      break;
    case URL_WRONLY:
    {
      /* srcpad */
      switch (whence) {
        case SEEK_SET:
          info->offset = (guint64) pos;
          gst_pad_push_event (info->pad, gst_event_new_new_segment
              (TRUE, 1.0, GST_FORMAT_BYTES, info->offset,
                  GST_CLOCK_TIME_NONE, info->offset));
          break;
        case SEEK_CUR:
          info->offset += pos;
          gst_pad_push_event (info->pad, gst_event_new_new_segment
              (TRUE, 1.0, GST_FORMAT_BYTES, info->offset,
                  GST_CLOCK_TIME_NONE, info->offset));
          break;
        default:
          break;
      }
      newpos = info->offset;
    }
      break;
    default:
      g_assert (0);
      break;
  }

  GST_DEBUG ("Now at offset %lld", info->offset);
  return newpos;
}