Exemple #1
0
static GstFlowReturn
mpegts_base_scan (MpegTSBase * base)
{
  GstFlowReturn ret = GST_FLOW_OK;
  GstBuffer *buf = NULL;
  guint i;
  gboolean done = FALSE;
  MpegTSPacketizerPacketReturn pret;
  gint64 tmpval;
  gint64 upstream_size, seek_pos, reverse_limit;
  GstFormat format;
  guint initial_pcr_seen;

  GST_DEBUG ("Scanning for initial sync point");

  /* Find initial sync point and at least 5 PCR values */
  for (i = 0; i < 20 && !done; i++) {
    GST_DEBUG ("Grabbing %d => %d", i * 65536, (i + 1) * 65536);

    ret = gst_pad_pull_range (base->sinkpad, i * 65536, 65536, &buf);
    if (G_UNLIKELY (ret == GST_FLOW_EOS))
      break;
    if (G_UNLIKELY (ret != GST_FLOW_OK))
      goto beach;

    /* Push to packetizer */
    mpegts_packetizer_push (base->packetizer, buf);
    buf = NULL;

    if (mpegts_packetizer_has_packets (base->packetizer)) {
      if (base->seek_offset == -1) {
        /* Mark the initial sync point and remember the packetsize */
        base->seek_offset = base->packetizer->offset;
        GST_DEBUG ("Sync point is now %" G_GUINT64_FORMAT, base->seek_offset);
        base->packetsize = base->packetizer->packet_size;
      }
      while (1) {
        /* Eat up all packets */
        pret = mpegts_packetizer_process_next_packet (base->packetizer);
        if (pret == PACKET_NEED_MORE)
          break;
        if (pret != PACKET_BAD && base->packetizer->nb_seen_offsets >= 5) {
          GST_DEBUG ("Got enough initial PCR");
          done = TRUE;
          break;
        }
      }
    }
  }

  initial_pcr_seen = base->packetizer->nb_seen_offsets;
  if (G_UNLIKELY (initial_pcr_seen == 0))
    goto no_initial_pcr;
  GST_DEBUG ("Seen %d initial PCR", initial_pcr_seen);

  /* Now send data from the end */

  /* Get the size of upstream */
  format = GST_FORMAT_BYTES;
  if (!gst_pad_peer_query_duration (base->sinkpad, format, &tmpval))
    goto beach;
  upstream_size = tmpval;

  /* The scanning takes place on the last 2048kB. Considering PCR should
   * be present at least every 100ms, this should cope with streams
   * up to 160Mbit/s */
  reverse_limit = MAX (0, upstream_size - 2097152);

  /* Find last PCR value, searching backwards by chunks of 300 MPEG-ts packets */
  for (seek_pos = MAX (0, upstream_size - 56400);
      seek_pos >= reverse_limit; seek_pos -= 56400) {
    mpegts_packetizer_clear (base->packetizer);
    GST_DEBUG ("Grabbing %" G_GUINT64_FORMAT " => %" G_GUINT64_FORMAT, seek_pos,
        seek_pos + 56400);

    ret = gst_pad_pull_range (base->sinkpad, seek_pos, 56400, &buf);
    if (G_UNLIKELY (ret == GST_FLOW_EOS))
      break;
    if (G_UNLIKELY (ret != GST_FLOW_OK))
      goto beach;

    /* Push to packetizer */
    mpegts_packetizer_push (base->packetizer, buf);
    buf = NULL;

    if (mpegts_packetizer_has_packets (base->packetizer)) {
      pret = PACKET_OK;
      /* Eat up all packets, really try to get last PCR(s) */
      while (pret != PACKET_NEED_MORE)
        pret = mpegts_packetizer_process_next_packet (base->packetizer);

      if (base->packetizer->nb_seen_offsets > initial_pcr_seen) {
        GST_DEBUG ("Got last PCR(s) (total seen:%d)",
            base->packetizer->nb_seen_offsets);
        break;
      }
    }
  }

beach:
  mpegts_packetizer_clear (base->packetizer);
  return ret;

no_initial_pcr:
  mpegts_packetizer_clear (base->packetizer);
  GST_WARNING_OBJECT (base, "Couldn't find any PCR within the first %d bytes",
      10 * 65536);
  return GST_FLOW_ERROR;
}
Exemple #2
0
static GstFlowReturn
mpegts_base_scan (MpegTSBase * base)
{
  GstFlowReturn ret = GST_FLOW_OK;
  GstBuffer *buf = NULL;
  guint i;
  gboolean done = FALSE;
  MpegTSPacketizerPacketReturn pret;
  gint64 tmpval;
  guint64 upstream_size, seek_pos;
  GstFormat format;
  guint initial_pcr_seen;

  GST_DEBUG ("Scanning for initial sync point");

  /* Find initial sync point and at least 5 PCR values */
  for (i = 0; i < 10 && !done; i++) {
    GST_DEBUG ("Grabbing %d => %d", i * 65536, 65536);

    ret = gst_pad_pull_range (base->sinkpad, i * 65536, 65536, &buf);
    if (G_UNLIKELY (ret != GST_FLOW_OK))
      goto beach;

    /* Push to packetizer */
    mpegts_packetizer_push (base->packetizer, buf);
    buf = NULL;

    if (mpegts_packetizer_has_packets (base->packetizer)) {
      if (base->seek_offset == -1) {
        /* Mark the initial sync point and remember the packetsize */
        base->seek_offset = base->packetizer->offset;
        GST_DEBUG ("Sync point is now %" G_GUINT64_FORMAT, base->seek_offset);
        base->packetsize = base->packetizer->packet_size;
      }
      while (1) {
        /* Eat up all packets */
        pret = mpegts_packetizer_process_next_packet (base->packetizer);
        if (pret == PACKET_NEED_MORE)
          break;
        if (pret != PACKET_BAD &&
            mpegts_packetizer_get_seen_pcr (base->packetizer) >= 5) {
          GST_DEBUG ("Got enough initial PCR");
          done = TRUE;
          break;
        }
      }
    }
  }

  initial_pcr_seen = mpegts_packetizer_get_seen_pcr (base->packetizer);
  if (G_UNLIKELY (initial_pcr_seen == 0))
    goto no_initial_pcr;
  GST_DEBUG ("Seen %d initial PCR", initial_pcr_seen);

  /* Now send data from the end */
  mpegts_packetizer_clear (base->packetizer);

  /* Get the size of upstream */
  format = GST_FORMAT_BYTES;
  if (!gst_pad_peer_query_duration (base->sinkpad, format, &tmpval))
    goto beach;
  upstream_size = tmpval;
  done = FALSE;

  /* Find last PCR value */
  for (seek_pos = MAX (0, upstream_size - 655360);
      seek_pos < upstream_size && !done; seek_pos += 65536) {
    GST_DEBUG ("Grabbing %" G_GUINT64_FORMAT " => %d", seek_pos, 65536);

    ret = gst_pad_pull_range (base->sinkpad, seek_pos, 65536, &buf);
    if (G_UNLIKELY (ret != GST_FLOW_OK))
      goto beach;

    /* Push to packetizer */
    mpegts_packetizer_push (base->packetizer, buf);
    buf = NULL;

    if (mpegts_packetizer_has_packets (base->packetizer)) {
      while (1) {
        /* Eat up all packets */
        pret = mpegts_packetizer_process_next_packet (base->packetizer);
        if (pret == PACKET_NEED_MORE)
          break;
        if (pret != PACKET_BAD &&
            mpegts_packetizer_get_seen_pcr (base->packetizer) >
            initial_pcr_seen) {
          GST_DEBUG ("Got last PCR");
          done = TRUE;
          break;
        }
      }
    }
  }

beach:
  mpegts_packetizer_clear (base->packetizer);
  return ret;

no_initial_pcr:
  mpegts_packetizer_clear (base->packetizer);
  GST_WARNING_OBJECT (base, "Couldn't find any PCR within the first %d bytes",
      10 * 65536);
  return GST_FLOW_ERROR;
}