Example #1
0
static void
gst_navseek_segseek (GstNavSeek * navseek)
{
  GstEvent *event;
  GstPad *peer_pad;

  if ((navseek->segment_start == GST_CLOCK_TIME_NONE) ||
      (navseek->segment_end == GST_CLOCK_TIME_NONE) ||
      (!GST_PAD_IS_LINKED (GST_BASE_TRANSFORM (navseek)->sinkpad))) {
    return;
  }

  if (navseek->loop) {
    event =
        gst_event_new_seek (1.0, GST_FORMAT_TIME,
        GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_SEGMENT,
        GST_SEEK_TYPE_SET, navseek->segment_start, GST_SEEK_TYPE_SET,
        navseek->segment_end);
  } else {
    event =
        gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_ACCURATE,
        GST_SEEK_TYPE_SET, navseek->segment_start, GST_SEEK_TYPE_SET,
        navseek->segment_end);
  }

  peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad);
  gst_pad_send_event (peer_pad, event);
  gst_object_unref (peer_pad);
}
Example #2
0
static gboolean
play_do_seek (GstElement * pipeline, gint64 pos, gdouble rate,
    GstPlayTrickMode mode)
{
  GstSeekFlags seek_flags;
  GstQuery *query;
  GstEvent *seek;
  gboolean seekable = FALSE;

  query = gst_query_new_seeking (GST_FORMAT_TIME);
  if (!gst_element_query (pipeline, query)) {
    gst_query_unref (query);
    return FALSE;
  }

  gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL);
  gst_query_unref (query);

  if (!seekable)
    return FALSE;

  seek_flags = GST_SEEK_FLAG_FLUSH;

  switch (mode) {
    case GST_PLAY_TRICK_MODE_DEFAULT:
      seek_flags |= GST_SEEK_FLAG_TRICKMODE;
      break;
    case GST_PLAY_TRICK_MODE_DEFAULT_NO_AUDIO:
      seek_flags |= GST_SEEK_FLAG_TRICKMODE | GST_SEEK_FLAG_TRICKMODE_NO_AUDIO;
      break;
    case GST_PLAY_TRICK_MODE_KEY_UNITS:
      seek_flags |= GST_SEEK_FLAG_TRICKMODE_KEY_UNITS;
      break;
    case GST_PLAY_TRICK_MODE_KEY_UNITS_NO_AUDIO:
      seek_flags |=
          GST_SEEK_FLAG_TRICKMODE_KEY_UNITS | GST_SEEK_FLAG_TRICKMODE_NO_AUDIO;
      break;
    case GST_PLAY_TRICK_MODE_NONE:
    default:
      break;
  }

  if (rate >= 0)
    seek = gst_event_new_seek (rate, GST_FORMAT_TIME,
        seek_flags | GST_SEEK_FLAG_ACCURATE,
        /* start */ GST_SEEK_TYPE_SET, pos,
        /* stop */ GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE);
  else
    seek = gst_event_new_seek (rate, GST_FORMAT_TIME,
        seek_flags | GST_SEEK_FLAG_ACCURATE,
        /* start */ GST_SEEK_TYPE_SET, 0,
        /* stop */ GST_SEEK_TYPE_SET, pos);

  if (!gst_element_send_event (pipeline, seek))
    return FALSE;

  cur_rate = rate;
  trick_mode = mode;
  return TRUE;
}
Example #3
0
void MediaImpl::resetMovie()
{
    // XXX: There used to be an issue that when we reached EOS (_eos() == true) we could not seek anymore.
    if (_seekEnabled)
    {
        qDebug() << "Seeking at position 0.";
        GstEvent* seek_event;

        if (_rate > 0) {
            seek_event = gst_event_new_seek (_rate, GST_FORMAT_TIME, GstSeekFlags( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
                                             GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, 0);
        } else {
            seek_event = gst_event_new_seek (_rate, GST_FORMAT_TIME, GstSeekFlags( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
                                             GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_END, 0);
        }
        /* Send the event */
        gst_element_send_event (_appsink0, seek_event);
//    gst_element_seek_simple (_pipeline, GST_FORMAT_TIME,
//                             (GstSeekFlags) (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT), 0);
//    this->_currentFrameSample = NULL;
        _setMovieReady(true);
    }
    else
    {
        // Just reload movie.
        qDebug() << "Reloading the movie" << _seekEnabled;
        loadMovie(_uri);
    }
}
Example #4
0
void  VideoImpl::_updateRate()
{
  // Check different things.
  if (_pipeline == NULL)
  {
    qWarning() << "Cannot set rate: no pipeline!" << endl;
    return;
  }

  if (!_seekEnabled)
  {
    qWarning() << "Cannot set rate: seek not working" << endl;
    return;
  }

  if (!_isMovieReady())
  {
    qWarning() << "Movie is not yet ready to play, cannot seek yet." << endl;
  }

  // Obtain the current position, needed for the seek event.
  gint64 position;
  if (!gst_element_query_position (_pipeline, GST_FORMAT_TIME, &position)) {
    qWarning() << "Unable to retrieve current position." << endl;
    return;
  }

  // Create the seek event.
  GstEvent *seekEvent;
  if (_rate > 0.0) {
    // Rate is positive (playing the video in normal direction)
    // Set new rate as a first argument. Provide position 0 so that we go to 0:00
    seekEvent = gst_event_new_seek (_rate, GST_FORMAT_TIME, GstSeekFlags( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
        GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_NONE, 0); // Go to 0:00
  } else {
    // Rate is negative
    // Set new rate as a first arguemnt. Provide the position we were already at.
    seekEvent = gst_event_new_seek (_rate, GST_FORMAT_TIME, GstSeekFlags( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
        GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, position);
  }

  // If we have not done so, obtain the sink through which we will send the seek events.
  if (_appsink0 == NULL) {
    g_object_get (_pipeline, "video-sink", &_appsink0, NULL);
  }

  // Send the event.
  if (!gst_element_send_event (_appsink0, seekEvent)) {
    qWarning() << "Cannot perform seek event" << endl;
  }

  qDebug() << "Current rate: " << _rate << "." << endl;
}
static void
check_correct_buffer (guint8 * src_data, guint src_size, guint8 * dst_data,
    guint dst_size)
{
  GstBuffer *buffer = gst_buffer_new_allocate (NULL, src_size, 0);
  GstBuffer *newBuffer;
  GstElement *avisubtitle = setup_avisubtitle ();
  GstEvent *event;

  fail_unless (g_list_length (buffers) == 0, "Buffers list needs to be empty");
  gst_buffer_fill (buffer, 0, src_data, src_size);
  fail_unless (gst_element_set_state (avisubtitle,
          GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
      "could not set to playing");
  ASSERT_BUFFER_REFCOUNT (buffer, "inbuffer", 1);
  event = gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
      GST_SEEK_TYPE_SET, 2 * GST_SECOND, GST_SEEK_TYPE_SET, 5 * GST_SECOND);
  fail_unless (gst_element_send_event (avisubtitle, event) == FALSE,
      "Seeking is not possible when there is no buffer yet");
  fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK,
      "not accepted a correct buffer");
  /* we gave away our reference to the buffer, don't assume anything */
  buffer = NULL;
  /* a new buffer is created in the list */
  fail_unless (g_list_length (buffers) == 1,
      "No new buffer in the buffers list");
  event = gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
      GST_SEEK_TYPE_SET, 2 * GST_SECOND, GST_SEEK_TYPE_SET, 5 * GST_SECOND);
  fail_unless (gst_element_send_event (avisubtitle, event) == TRUE,
      "seeking should be working now");
  fail_unless (g_list_length (buffers) == 2,
      "After seeking we need another buffer in the buffers");
  newBuffer = GST_BUFFER (buffers->data);
  buffers = g_list_remove (buffers, newBuffer);
  fail_unless (g_list_length (buffers) == 1, "Buffers list needs to be empty");
  fail_unless (gst_buffer_get_size (newBuffer) == dst_size,
      "size of the new buffer is wrong ( %d != %d)",
      gst_buffer_get_size (newBuffer), dst_size);
  fail_unless (gst_buffer_memcmp (newBuffer, 0, dst_data, dst_size) == 0,
      "data of the buffer is not correct");
  gst_buffer_unref (newBuffer);
  /* free the buffer from seeking */
  gst_buffer_unref (GST_BUFFER (buffers->data));
  buffers = g_list_remove (buffers, buffers->data);
  fail_unless (gst_element_set_state (avisubtitle,
          GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
  cleanup_avisubtitle (avisubtitle);
}
Example #6
0
static void
gst_navseek_seek (GstNavSeek * navseek, gint64 offset)
{
  gboolean ret;
  GstPad *peer_pad;
  gint64 peer_value;

  /* Query for the current time then attempt to set to time + offset */
  peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad);
  ret = gst_pad_query_position (peer_pad, GST_FORMAT_TIME, &peer_value);

  if (ret) {
    GstEvent *event;

    peer_value += offset;
    if (peer_value < 0)
      peer_value = 0;

    event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
        GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH,
        GST_SEEK_TYPE_SET, peer_value, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);

    gst_pad_send_event (peer_pad, event);
  }

  gst_object_unref (peer_pad);
}
Example #7
0
static void
gst_navseek_change_playback_rate (GstNavSeek * navseek, gdouble rate)
{
  gboolean ret;
  GstPad *peer_pad;
  gint64 current_position;

  peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad);
  ret = gst_pad_query_position (peer_pad, GST_FORMAT_TIME, &current_position);

  if (ret) {
    GstEvent *event;
    gint64 start;
    gint64 stop;

    if (rate > 0.0) {
      start = current_position;
      stop = -1;
    } else {
      /* negative rate: we play from stop to start */
      start = 0;
      stop = current_position;
    }

    event = gst_event_new_seek (rate, GST_FORMAT_TIME,
        GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP,
        GST_SEEK_TYPE_SET, start, GST_SEEK_TYPE_SET, stop);

    gst_pad_send_event (peer_pad, event);
  }
  gst_object_unref (peer_pad);
}
Example #8
0
gboolean eos_callback(GstPad *pad,
                      GstObject *parent,
                      GstEvent *event)
{
    GstEvent *seek_event;
    GstElement *bkgdec;
    GValue v=G_VALUE_INIT;
    GstPad *srcpad;
    GstIterator *srcpads;
    gboolean result;

    g_print("Decodebin received EOS. Someone should handle that...\n");
    
    bkgdec=gst_pad_get_parent_element(pad);
    if(bkgdec->numsrcpads>0) {
        srcpads=gst_element_iterate_src_pads(bkgdec);
        gst_iterator_next(srcpads,&v);
        srcpad=GST_PAD(g_value_get_object(&v));
        seek_event=gst_event_new_seek ( 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
                         GST_SEEK_TYPE_SET, 0,
                         GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);     
        result=gst_pad_send_event(srcpad,seek_event);
        if(result==TRUE) {
            g_print("seek event sent OK.\n");
        } else {
           g_print("seek sent FAILED.\n");
        }
        g_value_reset(&v);
        g_value_unset(&v);
        gst_iterator_free(srcpads);
        return TRUE;
    }
    return gst_pad_event_default(pad,parent,event);
}
Example #9
0
static gboolean
vorbis_dec_src_event (GstPad * pad, GstEvent * event)
{
  gboolean res = TRUE;
  GstVorbisDec *dec;

  dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
  if (G_UNLIKELY (dec == NULL)) {
    gst_event_unref (event);
    return FALSE;
  }

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEEK:
    {
      GstFormat format, tformat;
      gdouble rate;
      GstEvent *real_seek;
      GstSeekFlags flags;
      GstSeekType cur_type, stop_type;
      gint64 cur, stop;
      gint64 tcur, tstop;
      guint32 seqnum;

      gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
          &stop_type, &stop);
      seqnum = gst_event_get_seqnum (event);
      gst_event_unref (event);

      /* First bring the requested format to time */
      tformat = GST_FORMAT_TIME;
      if (!(res = vorbis_dec_convert (pad, format, cur, &tformat, &tcur)))
        goto convert_error;
      if (!(res = vorbis_dec_convert (pad, format, stop, &tformat, &tstop)))
        goto convert_error;

      /* then seek with time on the peer */
      real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME,
          flags, cur_type, tcur, stop_type, tstop);
      gst_event_set_seqnum (real_seek, seqnum);

      res = gst_pad_push_event (dec->sinkpad, real_seek);
      break;
    }
    default:
      res = gst_pad_push_event (dec->sinkpad, event);
      break;
  }
done:
  gst_object_unref (dec);

  return res;

  /* ERRORS */
convert_error:
  {
    GST_DEBUG_OBJECT (dec, "cannot convert start/stop for seek");
    goto done;
  }
}
Example #10
0
static gboolean
gst_au_parse_handle_seek (GstAuParse * auparse, GstEvent * event)
{
  GstSeekType start_type, stop_type;
  GstSeekFlags flags;
  GstFormat format;
  gdouble rate;
  gint64 start, stop;
  gboolean res;

  gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
      &stop_type, &stop);

  if (format != GST_FORMAT_TIME) {
    GST_DEBUG_OBJECT (auparse, "only support seeks in TIME format");
    return FALSE;
  }

  res = gst_au_parse_src_convert (auparse, GST_FORMAT_TIME, start,
      GST_FORMAT_BYTES, &start);

  if (stop > 0) {
    res = gst_au_parse_src_convert (auparse, GST_FORMAT_TIME, stop,
        GST_FORMAT_BYTES, &stop);
  }

  GST_INFO_OBJECT (auparse,
      "seeking: %" G_GINT64_FORMAT " ... %" G_GINT64_FORMAT, start, stop);

  event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, start_type, start,
      stop_type, stop);
  res = gst_pad_push_event (auparse->sinkpad, event);
  return res;
}
Example #11
0
static gboolean
gst_sub_parse_src_event (GstPad * pad, GstEvent * event)
{
  GstSubParse *self = GST_SUBPARSE (gst_pad_get_parent (pad));
  gboolean ret = FALSE;

  GST_DEBUG ("Handling %s event", GST_EVENT_TYPE_NAME (event));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEEK:
    {
      GstFormat format;
      GstSeekType start_type, stop_type;
      gint64 start, stop;
      gdouble rate;
      gboolean update;

      gst_event_parse_seek (event, &rate, &format, &self->segment_flags,
          &start_type, &start, &stop_type, &stop);

      if (format != GST_FORMAT_TIME) {
        GST_WARNING_OBJECT (self, "we only support seeking in TIME format");
        gst_event_unref (event);
        goto beach;
      }

      /* Convert that seek to a seeking in bytes at position 0,
         FIXME: could use an index */
      ret = gst_pad_push_event (self->sinkpad,
          gst_event_new_seek (rate, GST_FORMAT_BYTES, self->segment_flags,
              GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, 0));

      if (ret) {
        /* Apply the seek to our segment */
        gst_segment_set_seek (&self->segment, rate, format, self->segment_flags,
            start_type, start, stop_type, stop, &update);

        GST_DEBUG_OBJECT (self, "segment after seek: %" GST_SEGMENT_FORMAT,
            &self->segment);

        self->next_offset = 0;

        self->need_segment = TRUE;
      } else {
        GST_WARNING_OBJECT (self, "seek to 0 bytes failed");
      }

      gst_event_unref (event);
      break;
    }
    default:
      ret = gst_pad_event_default (pad, event);
      break;
  }

beach:
  gst_object_unref (self);

  return ret;
}
Example #12
0
void  MediaImpl::_updateRate()
{
    if (_pipeline == NULL)
    {
        qDebug() << "Cannot set rate: no pipeline!" << endl;
        return;
    }

    if (!_seekEnabled)
    {
        qDebug() << "Cannot set rate: seek not working" << endl;
        return;
    }

    if (!_isMovieReady())
    {
        qDebug() << "Movie is not yet ready to play, cannot seek yet." << endl;
    }

    gint64 position;
    GstEvent *seekEvent;

    /* Obtain the current position, needed for the seek event */
    if (!gst_element_query_position (_pipeline, GST_FORMAT_TIME, &position)) {
        g_printerr ("Unable to retrieve current position.\n");
        return;
    }

    /* Create the seek event */
    if (_rate > 0) {
        seekEvent = gst_event_new_seek (_rate, GST_FORMAT_TIME, GstSeekFlags( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
                                        GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_NONE, 0);
    } else {
        seekEvent = gst_event_new_seek (_rate, GST_FORMAT_TIME, GstSeekFlags( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
                                        GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, position);
    }

    if (_appsink0 == NULL) {
        /* If we have not done so, obtain the sink through which we will send the seek events */
        g_object_get (_pipeline, "video-sink", &_appsink0, NULL);
    }

    /* Send the event */
    gst_element_send_event (_appsink0, seekEvent);

    g_print ("Current rate: %g\n", _rate);
}
static gboolean
seek_mode_testing (InsanityTest * test)
{
  gboolean res;
  GstEvent *event;
  GstSeekFlags flags = GST_SEEK_FLAG_FLUSH;
  GstSeekType stop_type = GST_SEEK_TYPE_NONE;

  /* Reset global seek props */
  glob_seek_first_buf_ts = GST_CLOCK_TIME_NONE;
  glob_seek_stop_ts = GST_CLOCK_TIME_NONE;
  glob_seek_segment_seektime = 0;

  /* Set seeking arguments */
  switch (glob_in_progress) {
    case TEST_BACKWARD_PLAYBACK:
      glob_seek_rate = -1;
      glob_seek_stop_ts = glob_duration;
      stop_type = GST_SEEK_TYPE_SET;
      break;
    case TEST_FAST_FORWARD:
      glob_seek_rate = 2;
      glob_seek_stop_ts = glob_duration / 2;
      break;
    case TEST_FAST_BACKWARD:
      glob_seek_rate = -2;
      glob_seek_stop_ts = glob_duration;
      stop_type = GST_SEEK_TYPE_SET;
      break;
    default:
      return FALSE;
  }

  glob_seek_got_segment = FALSE;
  event = gst_event_new_seek (glob_seek_rate, GST_FORMAT_TIME,
      flags, GST_SEEK_TYPE_SET, glob_seek_segment_seektime,
      stop_type, glob_seek_stop_ts);

  /* We didn't find any event/message with the seqnum we previously set */
  if (glob_seqnum != 0 && glob_seqnum_found == FALSE)
    glob_wrong_seqnum = TRUE;

  glob_seqnum_found = FALSE;
  glob_seqnum = gst_util_seqnum_next ();
  gst_event_set_seqnum (event, glob_seqnum);
  res = gst_element_send_event (glob_pipeline, event);
  global_last_seek = g_get_monotonic_time ();

  if (!res) {
    validate_current_test (test, FALSE, "Could not send seek event");
    glob_seek_rate = 0;
    glob_seqnum = 0;

    /* ... Next test */
    next_test (test);
  }

  return FALSE;
}
Example #14
0
static void
run_seek_position_test (gdouble rate, GstSeekType start_type,
    guint64 seek_start, GstSeekType stop_type,
    guint64 seek_stop, GstSeekFlags flags, guint64 segment_start,
    guint64 segment_stop, gint segments)
{
  const guint segment_size = 60 * TS_PACKET_LEN;
  const gchar *manifest =
      "#EXTM3U \n"
      "#EXT-X-TARGETDURATION:1\n"
      "#EXTINF:1,Test\n" "001.ts\n"
      "#EXTINF:1,Test\n" "002.ts\n"
      "#EXTINF:1,Test\n" "003.ts\n"
      "#EXTINF:1,Test\n" "004.ts\n" "#EXT-X-ENDLIST\n";
  GstHlsDemuxTestInputData inputTestData[] = {
    {"http://unit.test/media.m3u8", (guint8 *) manifest, 0},
    {"http://unit.test/001.ts", NULL, segment_size},
    {"http://unit.test/002.ts", NULL, segment_size},
    {"http://unit.test/003.ts", NULL, segment_size},
    {"http://unit.test/004.ts", NULL, segment_size},
    {NULL, NULL, 0},
  };
  GstAdaptiveDemuxTestExpectedOutput outputTestData[] = {
    {"src_0", segment_size * segments, NULL},
    {NULL, 0, NULL}
  };
  GstTestHTTPSrcCallbacks http_src_callbacks = { 0 };
  GstAdaptiveDemuxTestCase *engineTestData;
  GstHlsDemuxTestCase hlsTestCase = { 0 };
  GByteArray *mpeg_ts = NULL;

  engineTestData = gst_adaptive_demux_test_case_new ();
  mpeg_ts = setup_test_variables (inputTestData, outputTestData,
      &hlsTestCase, engineTestData, segment_size);

  http_src_callbacks.src_start = gst_hlsdemux_test_src_start;
  http_src_callbacks.src_create = gst_hlsdemux_test_src_create;

  /* FIXME hack to avoid having a 0 seqnum */
  gst_util_seqnum_next ();

  /* Seek to 1.5s, expect it to start from 1s */
  engineTestData->threshold_for_seek = 20 * TS_PACKET_LEN;
  engineTestData->seek_event =
      gst_event_new_seek (rate, GST_FORMAT_TIME, flags, start_type,
      seek_start, stop_type, seek_stop);
  gst_segment_init (&outputTestData[0].post_seek_segment, GST_FORMAT_TIME);
  outputTestData[0].post_seek_segment.rate = rate;
  outputTestData[0].post_seek_segment.start = segment_start;
  outputTestData[0].post_seek_segment.time = segment_start;
  outputTestData[0].post_seek_segment.stop = segment_stop;
  outputTestData[0].segment_verification_needed = TRUE;

  gst_test_http_src_install_callbacks (&http_src_callbacks, &hlsTestCase);
  gst_adaptive_demux_test_seek (DEMUX_ELEMENT_NAME,
      inputTestData[0].uri, engineTestData);

  TESTCASE_UNREF_BOILERPLATE;
}
static gboolean
gst_y4m_dec_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
  gboolean res;
  GstY4mDec *y4mdec;

  y4mdec = GST_Y4M_DEC (parent);

  GST_DEBUG_OBJECT (y4mdec, "event");

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEEK:
    {
      gdouble rate;
      GstFormat format;
      GstSeekFlags flags;
      GstSeekType start_type, stop_type;
      gint64 start, stop;
      gint64 framenum;
      guint64 byte;

      gst_event_parse_seek (event, &rate, &format, &flags, &start_type,
          &start, &stop_type, &stop);

      if (format != GST_FORMAT_TIME) {
        res = FALSE;
        break;
      }

      framenum = gst_y4m_dec_timestamp_to_frames (y4mdec, start);
      GST_DEBUG ("seeking to frame %" G_GINT64_FORMAT, framenum);
      if (framenum == -1) {
        res = FALSE;
        break;
      }

      byte = gst_y4m_dec_frames_to_bytes (y4mdec, framenum);
      GST_DEBUG ("offset %" G_GUINT64_FORMAT, (guint64) byte);
      if (byte == -1) {
        res = FALSE;
        break;
      }

      gst_event_unref (event);
      event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags,
          start_type, byte, stop_type, -1);

      res = gst_pad_push_event (y4mdec->sinkpad, event);
    }
      break;
    default:
      res = gst_pad_event_default (pad, parent, event);
      break;
  }

  return res;
}
Example #16
0
static void update_playback_speed() {
	gboolean error;
	gint64 pos = gstreamer_get_position(&error);
	if (error)
		return;
	GstElement *video_sink = get_video_sink();
	if (!video_sink)
		return;
	GstEvent *seek_event;
	if (playback_rate > 0)
		seek_event = gst_event_new_seek(playback_rate, GST_FORMAT_TIME,
			GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
			GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_NONE, 0);
	else
		seek_event = gst_event_new_seek (playback_rate, GST_FORMAT_TIME,
			GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
			GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, pos);
	gst_element_send_event (video_sink, seek_event);
}
Example #17
0
static GstFlowReturn progress_buffer_getrange(GstPad *pad, GstObject *parent, guint64 start_position,
                                              guint size, GstBuffer **buffer)
{
#if ENABLE_PULL_MODE
    ProgressBuffer *element = PROGRESS_BUFFER(parent);
    GstFlowReturn  result = GST_FLOW_OK;
    guint64        end_position = start_position + size;
    gboolean       needs_seeking = FALSE;

    g_mutex_lock(&element->lock); // Use one lock for push and pull modes

    if (element->sink_segment.stop < (gint64)end_position)
        result = GST_FLOW_EOS;
    else if (element->sink_segment.start <= (gint64)start_position &&
             element->sink_segment.position >= (gint64)end_position)
        result = cache_read_buffer_from_position(element->cache, start_position, size, buffer);
    else
    {
#if ENABLE_SOURCE_SEEKING
        needs_seeking = element->sink_segment.start > (gint64)start_position;
        if (needs_seeking)
        {
            element->range_start = start_position;
            reset_eos(element, TRUE);
        }
#endif
        if (element->sink_segment.position < (gint64)end_position)
        {
            element->range_stop = end_position + (gint64)(element->bandwidth * element->prebuffer_time);

            if (element->sink_segment.stop < element->range_stop)
                element->range_stop = element->sink_segment.stop;

#if ENABLE_SOURCE_SEEKING
            needs_seeking = element->bandwidth > 0 &&
                end_position - element->sink_segment.position > element->bandwidth * element->wait_tolerance;
#endif
        }

        send_underrun_message(element);
        result = GST_FLOW_FLUSHING;
    }

    g_mutex_unlock(&element->lock);

    if (needs_seeking)
        gst_pad_push_event(element->sinkpad, gst_event_new_seek(element->sink_segment.rate, GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
            GST_SEEK_TYPE_SET, start_position, GST_SEEK_TYPE_NONE, 0));

    return result;
#else
    ProgressBuffer *element = PROGRESS_BUFFER(GST_PAD_PARENT(pad));
    return gst_pad_pull_range(element->sinkpad, parent, start_position, size, buffer);
#endif
}
static gboolean
gst_raw_parse_handle_seek_push (GstRawParse * rp, GstEvent * event)
{
  GstFormat format;
  gdouble rate;
  GstSeekFlags flags;
  GstSeekType start_type, stop_type;
  gint64 start, stop;
  gboolean ret = FALSE;

  gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
      &stop_type, &stop);

  /* can't seek backwards yet */
  if (rate <= 0.0)
    goto wrong_rate;

  /* First try if upstream handles the seek */
  ret = gst_pad_push_event (rp->sinkpad, event);
  if (ret)
    return ret;

  /* Otherwise convert to bytes and push upstream */
  if (format == GST_FORMAT_TIME || format == GST_FORMAT_DEFAULT) {
    ret = gst_raw_parse_convert (rp, format, start, GST_FORMAT_BYTES, &start);
    ret &= gst_raw_parse_convert (rp, format, stop, GST_FORMAT_BYTES, &stop);

    if (ret) {
      /* Seek on a frame boundary */
      start -= start % rp->framesize;
      if (stop != -1)
        stop += rp->framesize - stop % rp->framesize;

      event =
          gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, start_type,
          start, stop_type, stop);

      ret = gst_pad_push_event (rp->sinkpad, event);
    } else {
      GST_DEBUG_OBJECT (rp, "Seek failed: couldn't convert to byte positions");
    }
  } else {
    GST_DEBUG_OBJECT (rp,
        "seeking is only supported in TIME or DEFAULT format");
  }
  return ret;

  /* ERRORS */
wrong_rate:
  {
    GST_DEBUG_OBJECT (rp, "Seek failed: negative rates not supported yet");
    return FALSE;
  }
}
static gboolean
wait_and_do_seek (gpointer data)
{
  InsanityTest *test = data;
  GstEvent *event;
  gboolean res;

  if (GST_CLOCK_TIME_IS_VALID (glob_wait_time)) {
    GstClockTime cur = hls_test_get_position (test);

    if (glob_first_wait == 0)
      glob_first_wait = g_get_monotonic_time ();

    if (cur < glob_wait_time) {
      guint64 diff = g_get_monotonic_time () - glob_first_wait;

      if (diff > glob_playback_time * G_USEC_PER_SEC + PLAY_TIMEOUT)
        glob_play_in_time = FALSE;
      else
        return TRUE;
    }
  }

  glob_first_wait = 0;

  LOG ("Seeking at %i\n", seek_targets[glob_seek_nb].perc);

  /* If duration did not become known yet, we cannot test */
  if (!GST_CLOCK_TIME_IS_VALID (glob_duration)) {
    insanity_test_validate_checklist_item (test, "duration-known", FALSE, NULL);
    insanity_test_done (test);
    return FALSE;
  }

  glob_target = gst_util_uint64_scale (glob_duration,
      seek_targets[glob_seek_nb].perc, 100);

  event = gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
      GST_SEEK_TYPE_SET, glob_target, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);

  glob_validate_on_playing = "seek";
  res = gst_element_send_event (glob_pipeline, event);
  if (!res) {
    glob_validate_on_playing = NULL;
    insanity_test_validate_checklist_item (test, "seek", FALSE,
        "Failed to send seek event");
    return FALSE;
  }
  seek_targets[glob_seek_nb].seeked = TRUE;
  gst_element_get_state (glob_pipeline, NULL, NULL, SEEK_TIMEOUT);
  insanity_test_validate_checklist_item (test, "seek", TRUE, NULL);

  return FALSE;
}
Example #20
0
static void
pipeline_seek (APP_STATE_T * state, gint64 position)
{
  if (state->pipeline) {
    GstEvent *event;
    event = gst_event_new_seek (1.0,
        GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT,
        GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE);
    if (!gst_element_send_event (state->vsink, event)) {
      g_print ("seek failed\n");
    }
  }
}
Example #21
0
void MediaPlayer::seekTo(qint64 pos)
{
    // Seek with m_tempoRate is also used to change the tempo (that's actually the only way in GStreamer)
    GstEvent * seek_event = gst_event_new_seek( m_tempoRate,
                                                GST_FORMAT_TIME,
                                                (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
                                                GST_SEEK_TYPE_SET,
                                                pos * GST_MSECOND,
                                                GST_SEEK_TYPE_NONE,
                                                0 );

    gst_element_send_event( m_gst_pipeline, seek_event );
}
/*
 *  PsychGSSetMovieTimeIndex()  -- Set current playback time of movie, perform active seek if needed.
 */
double PsychGSSetMovieTimeIndex(int moviehandle, double timeindex, psych_bool indexIsFrames)
{
    GstElement		*theMovie;
    double		oldtime;
    long		targetIndex;
    GstEvent            *event;
    
    if (moviehandle < 0 || moviehandle >= PSYCH_MAX_MOVIES) {
        PsychErrorExitMsg(PsychError_user, "Invalid moviehandle provided!");
    }
    
    // Fetch references to objects we need:
    theMovie = movieRecordBANK[moviehandle].theMovie;    
    if (theMovie == NULL) {
        PsychErrorExitMsg(PsychError_user, "Invalid moviehandle provided. No movie associated with this handle !!!");
    }
    
    // Retrieve current timeindex:
    oldtime = PsychGSGetMovieTimeIndex(moviehandle);

    // TODO NOTE: We could use GST_SEEK_FLAG_SKIP to allow framedropping on fast forward/reverse playback...

    // Index based or target time based seeking?
    if (indexIsFrames) {
	// Index based seeking:		
	// TODO FIXME: This doesn't work (well) at all! Something's wrong here...
	// Seek to given targetIndex:
	targetIndex = (long) (timeindex + 0.5);

	// Simple seek, frame buffer (index) oriented, with pipeline flush and accurate seek,
	// i.e., not locked to keyframes, but frame-accurate: GST_FORMAT_DEFAULT?
	// gst_element_seek_simple(theMovie, GST_FORMAT_BUFFERS, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, targetIndex);
	event = gst_event_new_seek(1.0, GST_FORMAT_BUFFERS, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
				   GST_SEEK_TYPE_SET, targetIndex, GST_SEEK_TYPE_END, 0);
	gst_element_send_event(theMovie, event);
    }
    else {
	// Time based seeking:
	// Set new timeindex as time in seconds:

	// Simple seek, time-oriented, with pipeline flush and accurate seek,
	// i.e., not locked to keyframes, but frame-accurate:
	gst_element_seek_simple(theMovie, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, (gint64) (timeindex * (double) 1e9));
    }

    // Block until seek completed, failed or timeout of 30 seconds reached:
    gst_element_get_state(theMovie, NULL, NULL, (GstClockTime) (30 * 1e9));

    // Return old time value of previous position:
    return(oldtime);
}
Example #23
0
static gboolean
speex_dec_src_event (GstPad * pad, GstEvent * event)
{
  gboolean res = FALSE;
  GstSpeexDec *dec = GST_SPEEX_DEC (gst_pad_get_parent (pad));

  GST_LOG_OBJECT (dec, "handling %s event", GST_EVENT_TYPE_NAME (event));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEEK:{
      GstFormat format, tformat;
      gdouble rate;
      GstEvent *real_seek;
      GstSeekFlags flags;
      GstSeekType cur_type, stop_type;
      gint64 cur, stop;
      gint64 tcur, tstop;

      gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
          &stop_type, &stop);

      /* we have to ask our peer to seek to time here as we know
       * nothing about how to generate a granulepos from the src
       * formats or anything.
       *
       * First bring the requested format to time
       */
      tformat = GST_FORMAT_TIME;
      if (!(res = speex_dec_convert (pad, format, cur, &tformat, &tcur)))
        break;
      if (!(res = speex_dec_convert (pad, format, stop, &tformat, &tstop)))
        break;

      /* then seek with time on the peer */
      real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME,
          flags, cur_type, tcur, stop_type, tstop);

      GST_LOG_OBJECT (dec, "seek to %" GST_TIME_FORMAT, GST_TIME_ARGS (tcur));

      res = gst_pad_push_event (dec->sinkpad, real_seek);
      gst_event_unref (event);
      break;
    }
    default:
      res = gst_pad_event_default (pad, event);
      break;
  }

  gst_object_unref (dec);
  return res;
}
Example #24
0
static gboolean
speed_src_event (GstPad * pad, GstEvent * event)
{
  GstSpeed *filter;
  gboolean ret = FALSE;

  filter = GST_SPEED (gst_pad_get_parent (pad));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEEK:{
      gdouble rate;
      GstFormat format;
      GstSeekFlags flags;
      GstSeekType start_type, stop_type;
      gint64 start, stop;

      gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
          &stop_type, &stop);
      gst_event_unref (event);

      if (format != GST_FORMAT_TIME) {
        GST_DEBUG_OBJECT (filter, "only support seeks in TIME format");
        break;
      }

      if (start_type != GST_SEEK_TYPE_NONE && start != -1) {
        start *= filter->speed;
      }

      if (stop_type != GST_SEEK_TYPE_NONE && stop != -1) {
        stop *= filter->speed;
      }

      event = gst_event_new_seek (rate, format, flags, start_type, start,
          stop_type, stop);

      GST_LOG ("sending seek event: %" GST_PTR_FORMAT, event->structure);

      ret = gst_pad_send_event (GST_PAD_PEER (filter->sinkpad), event);
      break;
    }
    default:
      ret = gst_pad_event_default (pad, event);
      break;
  }

  gst_object_unref (filter);
  return ret;

}
Example #25
0
static VALUE
seek_initialize(VALUE self, VALUE rate, VALUE format, VALUE flags,
   VALUE start_type, VALUE start, VALUE stop_type, VALUE stop)
{
    GstEvent *event;

    event = gst_event_new_seek(NUM2DBL(rate),
                               RVAL2GST_FORMAT(format),
                               RVAL2GFLAGS(flags, GST_TYPE_SEEK_FLAGS),
                               RVAL2GENUM(start_type, GST_TYPE_SEEK_TYPE),
                               NUM2ULL(start),
                               RVAL2GENUM(stop_type, GST_TYPE_SEEK_TYPE),
                               NUM2ULL(stop));

    G_INITIALIZE(self, event);
    return Qnil;
}
Example #26
0
static gboolean
gst_uri_downloader_set_range (GstUriDownloader * downloader,
    gint64 range_start, gint64 range_end)
{
  g_return_val_if_fail (range_start >= 0, FALSE);
  g_return_val_if_fail (range_end >= -1, FALSE);

  if (range_start || (range_end >= 0)) {
    GstEvent *seek;

    seek = gst_event_new_seek (1.0, GST_FORMAT_BYTES, GST_SEEK_FLAG_FLUSH,
        GST_SEEK_TYPE_SET, range_start, GST_SEEK_TYPE_SET, range_end);

    return gst_element_send_event (downloader->priv->urisrc, seek);
  }
  return TRUE;
}
Example #27
0
static void
speed_cb (GtkWidget * widget)
{
  GstEvent *s_event;
  gboolean res;

  GST_DEBUG ("speed change");
  cur_speed = gtk_range_get_value (GTK_RANGE (widget));

  if (cur_speed == 0.0)
    return;

  s_event = gst_event_new_seek (cur_speed,
      GST_FORMAT_TIME, 0, GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_NONE, -1);

  res = gst_element_send_event (pipeline, s_event);
  if (!res)
    g_print ("speed change failed\n");
}
static void
loop_segment_done (GstBus * bus, GstMessage * message, GstElement * bin)
{
  GST_INFO ("bus message from \"%" GST_PTR_FORMAT "\": %" GST_PTR_FORMAT,
      GST_MESSAGE_SRC (message), message);

  if (looped) {
    g_main_loop_quit (main_loop);
  } else {
    GstEvent *seek_event;
    gboolean res;

    seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
        GST_SEEK_FLAG_SEGMENT,
        GST_SEEK_TYPE_SET, (GstClockTime) 0,
        GST_SEEK_TYPE_SET, (GstClockTime) 1 * GST_SECOND);

    res = gst_element_send_event (bin, seek_event);
    fail_unless (res == TRUE, NULL);
    looped = TRUE;
  }
}
Example #29
0
static gboolean
gst_vcd_parse_src_event (GstPad * pad, GstEvent * event)
{
  GstVcdParse *vcd = GST_VCD_PARSE (gst_pad_get_parent (pad));
  gboolean res;

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEEK:{
      GstSeekType start_type, stop_type;
      GstSeekFlags flags;
      GstFormat format;
      gdouble rate;
      gint64 start, stop;

      gst_event_parse_seek (event, &rate, &format, &flags, &start_type,
          &start, &stop_type, &stop);

      if (format == GST_FORMAT_BYTES) {
        gst_event_unref (event);
        if (start_type != GST_SEEK_TYPE_NONE)
          start = gst_vcd_parse_get_in_offset (start);
        if (stop_type != GST_SEEK_TYPE_NONE)
          stop = gst_vcd_parse_get_in_offset (stop);
        event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, start_type,
            start, stop_type, stop);
      } else {
        GST_WARNING_OBJECT (vcd, "seek event in non-byte format");
      }
      res = gst_pad_event_default (pad, event);
      break;
    }
    default:
      res = gst_pad_event_default (pad, event);
      break;
  }

  gst_object_unref (vcd);
  return res;
}
Example #30
0
gboolean command_seek (const char* line) {
    gboolean result = FALSE;
    gint direction = 0;
    gint64 useconds;
    gint64 position = 0LL;
    GstEvent* seek_event;
    g_return_val_if_fail (line != NULL, FALSE);
    if (g_str_has_prefix (line, "+")) {
        direction = 1;
    } else {
        if (g_str_has_prefix (line, "-")) {
            direction = -1;
        } else {
            direction = 0;
        }
    }
    if (direction != 0) {
        line = g_utf8_next_char (line);
    }
    useconds = (gint64) (g_ascii_strtod (line, NULL) * GST_SECOND);
    if (direction != 0) {
        GstFormat time_format;
        time_format = GST_FORMAT_TIME;
        if (gst_element_query_position ((GstElement*) pipeline, &time_format, &position)) {
            position = position + (useconds * direction);
        } else {
            g_printerr ("Could not get the current position\n");
            result = FALSE;
            return result;
        }
    } else {
        position = useconds;
    }
    seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_NONE, (gint64) 0);
    result = gst_element_send_event ((GstElement*) pipeline, _gst_event_ref0 (seek_event));
    _gst_event_unref0 (seek_event);
    return result;
}