Beispiel #1
0
/* seek to time, will be called when we operate in push mode. In pull mode we
 * get the requested byte offset. */
static gboolean
gst_lv2_source_do_seek (GstBaseSrc * base, GstSegment * segment)
{
  GstLV2Source *lv2 = (GstLV2Source *) base;
  GstClockTime time;
  gint samplerate, bpf;
  gint64 next_sample;

  GST_DEBUG_OBJECT (lv2, "seeking %" GST_SEGMENT_FORMAT, segment);

  time = segment->position;
  lv2->reverse = (segment->rate < 0.0);

  samplerate = GST_AUDIO_INFO_RATE (&lv2->info);
  bpf = GST_AUDIO_INFO_BPF (&lv2->info);

  /* now move to the time indicated, don't seek to the sample *after* the time */
  next_sample = gst_util_uint64_scale_int (time, samplerate, GST_SECOND);
  lv2->next_byte = next_sample * bpf;
  if (samplerate == 0)
    lv2->next_time = 0;
  else
    lv2->next_time =
        gst_util_uint64_scale_round (next_sample, GST_SECOND, samplerate);

  GST_DEBUG_OBJECT (lv2, "seeking next_sample=%" G_GINT64_FORMAT
      " next_time=%" GST_TIME_FORMAT, next_sample,
      GST_TIME_ARGS (lv2->next_time));

  g_assert (lv2->next_time <= time);

  lv2->next_sample = next_sample;

  if (!lv2->reverse) {
    if (GST_CLOCK_TIME_IS_VALID (segment->start)) {
      segment->time = segment->start;
    }
  } else {
    if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
      segment->time = segment->stop;
    }
  }

  if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
    time = segment->stop;
    lv2->sample_stop =
        gst_util_uint64_scale_round (time, samplerate, GST_SECOND);
    lv2->check_seek_stop = TRUE;
  } else {
    lv2->check_seek_stop = FALSE;
  }
  lv2->eos_reached = FALSE;

  return TRUE;
}
static void
fakesink_handoff_cb (GstElement * object, GstBuffer * buffer, GstPad * pad,
    gpointer user_data)
{
  TimestampDriftCtx *ctx = user_data;

  ctx->out_buffer_count++;
  if (ctx->latency == GST_CLOCK_TIME_NONE) {
    ctx->latency = 1000 - gst_buffer_get_size (buffer) / 8;
  }

  /* Check if we have a perfectly timestamped stream */
  if (ctx->next_out_ts != GST_CLOCK_TIME_NONE)
    fail_unless (ctx->next_out_ts == GST_BUFFER_TIMESTAMP (buffer),
        "expected timestamp %" GST_TIME_FORMAT " got timestamp %"
        GST_TIME_FORMAT, GST_TIME_ARGS (ctx->next_out_ts),
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));

  /* Check if we have a perfectly offsetted stream */
  fail_unless (GST_BUFFER_OFFSET_END (buffer) ==
      GST_BUFFER_OFFSET (buffer) + gst_buffer_get_size (buffer) / 8,
      "expected offset end %" G_GUINT64_FORMAT " got offset end %"
      G_GUINT64_FORMAT,
      GST_BUFFER_OFFSET (buffer) + gst_buffer_get_size (buffer) / 8,
      GST_BUFFER_OFFSET_END (buffer));
  if (ctx->next_out_off != GST_BUFFER_OFFSET_NONE) {
    fail_unless (GST_BUFFER_OFFSET (buffer) == ctx->next_out_off,
        "expected offset %" G_GUINT64_FORMAT " got offset %" G_GUINT64_FORMAT,
        ctx->next_out_off, GST_BUFFER_OFFSET (buffer));
  }

  if (ctx->in_buffer_count != ctx->out_buffer_count) {
    GST_INFO ("timestamp %" GST_TIME_FORMAT,
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
  }

  if (ctx->in_ts != GST_CLOCK_TIME_NONE && ctx->in_buffer_count > 1
      && ctx->in_buffer_count == ctx->out_buffer_count) {
    fail_unless (GST_BUFFER_TIMESTAMP (buffer) ==
        ctx->in_ts - gst_util_uint64_scale_round (ctx->latency, GST_SECOND,
            4096),
        "expected output timestamp %" GST_TIME_FORMAT " (%" G_GUINT64_FORMAT
        ") got output timestamp %" GST_TIME_FORMAT " (%" G_GUINT64_FORMAT ")",
        GST_TIME_ARGS (ctx->in_ts - gst_util_uint64_scale_round (ctx->latency,
                GST_SECOND, 4096)),
        ctx->in_ts - gst_util_uint64_scale_round (ctx->latency, GST_SECOND,
            4096), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
        GST_BUFFER_TIMESTAMP (buffer));
  }

  ctx->next_out_ts =
      GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer);
  ctx->next_out_off = GST_BUFFER_OFFSET_END (buffer);
}
static GstFlowReturn
gst_video_rate_trans_ip_max_avg (GstVideoRate * videorate, GstBuffer * buf)
{
  GstClockTime ts = GST_BUFFER_TIMESTAMP (buf);

  videorate->in++;

  if (!GST_CLOCK_TIME_IS_VALID (ts) || videorate->wanted_diff == 0)
    goto push;

  /* drop frames if they exceed our output rate */
  if (GST_CLOCK_TIME_IS_VALID (videorate->last_ts)) {
    GstClockTimeDiff diff = ts - videorate->last_ts;

    /* Drop buffer if its early compared to the desired frame rate and
     * the current average is higher than the desired average
     */
    if (diff < videorate->wanted_diff &&
        videorate->average < videorate->wanted_diff)
      goto drop;

    /* Update average */
    if (videorate->average) {
      GstClockTimeDiff wanted_diff;

      if (G_LIKELY (videorate->average_period > videorate->wanted_diff))
        wanted_diff = videorate->wanted_diff;
      else
        wanted_diff = videorate->average_period * 10;

      videorate->average =
          gst_util_uint64_scale_round (videorate->average,
          videorate->average_period - wanted_diff,
          videorate->average_period) +
          gst_util_uint64_scale_round (diff, wanted_diff,
          videorate->average_period);
    } else {
      videorate->average = diff;
    }
  }

  videorate->last_ts = ts;

push:
  videorate->out++;
  return GST_FLOW_OK;

drop:
  if (!videorate->silent)
    gst_video_rate_notify_drop (videorate);
  return GST_BASE_TRANSFORM_FLOW_DROPPED;
}
Beispiel #4
0
static GstBuffer *
create_test_buffer (guint64 num)
{
  GstBuffer *buffer;
  guint64 *data = g_malloc (sizeof (guint64));

  *data = num;

  buffer = gst_buffer_new_wrapped (data, sizeof (guint64));

  GST_BUFFER_PTS (buffer) =
      gst_util_uint64_scale_round (num, GST_SECOND, TEST_MSECS_PER_SAMPLE);
  GST_BUFFER_DURATION (buffer) =
      gst_util_uint64_scale_round (1, GST_SECOND, TEST_MSECS_PER_SAMPLE);

  return buffer;
}
static gboolean
gst_audio_fx_base_fir_filter_query (GstPad * pad, GstQuery * query)
{
  GstAudioFXBaseFIRFilter *self =
      GST_AUDIO_FX_BASE_FIR_FILTER (gst_pad_get_parent (pad));
  gboolean res = TRUE;

  switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_LATENCY:
    {
      GstClockTime min, max;
      gboolean live;
      guint64 latency;
      GstPad *peer;
      gint rate = GST_AUDIO_FILTER (self)->format.rate;

      if (rate == 0) {
        res = FALSE;
      } else if ((peer = gst_pad_get_peer (GST_BASE_TRANSFORM (self)->sinkpad))) {
        if ((res = gst_pad_query (peer, query))) {
          gst_query_parse_latency (query, &live, &min, &max);

          GST_DEBUG_OBJECT (self, "Peer latency: min %"
              GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
              GST_TIME_ARGS (min), GST_TIME_ARGS (max));

          if (self->fft && !self->low_latency)
            latency = self->block_length - self->kernel_length + 1;
          else
            latency = self->latency;

          /* add our own latency */
          latency = gst_util_uint64_scale_round (latency, GST_SECOND, rate);

          GST_DEBUG_OBJECT (self, "Our latency: %"
              GST_TIME_FORMAT, GST_TIME_ARGS (latency));

          min += latency;
          if (max != GST_CLOCK_TIME_NONE)
            max += latency;

          GST_DEBUG_OBJECT (self, "Calculated total latency : min %"
              GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
              GST_TIME_ARGS (min), GST_TIME_ARGS (max));

          gst_query_set_latency (query, live, min, max);
        }
        gst_object_unref (peer);
      }
      break;
    }
    default:
      res = gst_pad_query_default (pad, query);
      break;
  }
  gst_object_unref (self);
  return res;
}
Beispiel #6
0
static gboolean
gstbt_wave_replay_process (GstBtAudioSynth * base, GstBuffer * data,
    GstMapInfo * info)
{
  GstBtWaveReplay *src = ((GstBtWaveReplay *) base);

  if (src->osc->process) {
    gint16 *d = (gint16 *) info->data;
    guint ct = ((GstBtAudioSynth *) src)->generate_samples_per_buffer;
    guint64 off = gst_util_uint64_scale_round (GST_BUFFER_TIMESTAMP (data),
        base->samplerate, GST_SECOND);

    return src->osc->process (src->osc, off, ct, d);
  }
  return FALSE;
}
Beispiel #7
0
static gboolean
gst_wavenc_parse_cue (GstWavEnc * wavenc, guint32 id, GstTocEntry * entry)
{
  gint64 start;
  GstWavEncCue *cue;

  g_return_val_if_fail (entry != NULL, FALSE);

  gst_toc_entry_get_start_stop_times (entry, &start, NULL);

  cue = g_new (GstWavEncCue, 1);
  cue->id = id;
  cue->position = gst_util_uint64_scale_round (start, wavenc->rate, GST_SECOND);
  memcpy (cue->data_chunk_id, "data", 4);
  cue->chunk_start = 0;
  cue->block_start = 0;
  cue->sample_offset = cue->position;
  wavenc->cues = g_list_append (wavenc->cues, cue);

  return TRUE;
}
static guint
nanotime_to_sample (GstClockTime nanotime)
{
  return gst_util_uint64_scale_round (nanotime, SAMPLE_FREQ, GST_SECOND);
}
Beispiel #9
0
/**
 * gst_video_guess_framerate:
 * @duration: Nominal duration of one frame
 * @dest_n: (out) (allow-none): Numerator of the calculated framerate
 * @dest_d: (out) (allow-none): Denominator of the calculated framerate
 *
 * Given the nominal duration of one video frame,
 * this function will check some standard framerates for
 * a close match (within 0.1%) and return one if possible,
 *
 * It will calculate an arbitrary framerate if no close
 * match was found, and return %FALSE.
 *
 * It returns %FALSE if a duration of 0 is passed.
 *
 * Returns: %TRUE if a close "standard" framerate was
 * recognised, and %FALSE otherwise.
 *
 * Since: 1.6
 */
gboolean
gst_video_guess_framerate (GstClockTime duration, gint * dest_n, gint * dest_d)
{
  const int common_den[] = { 1, 2, 3, 4, 1001 };
  int best_n, best_d, gcd;
  guint64 best_error = G_MAXUINT64;
  guint64 a;
  int i;

  if (G_UNLIKELY (duration == 0))
    return FALSE;

  /* Use a limited precision conversion by default for more sensible results,
   * unless the frame duration is absurdly small (high speed cameras?) */
  if (duration > 100000) {
    best_n = GST_SECOND / 10000;
    best_d = duration / 10000;
  } else {
    best_n = GST_SECOND;
    best_d = duration;
  }

  for (i = 0; i < G_N_ELEMENTS (common_den); i++) {
    gint d = common_den[i];
    gint n = gst_util_uint64_scale_round (d, GST_SECOND, duration);

    /* For NTSC framerates, round to the nearest 1000 fps */
    if (d == 1001) {
      n += 500;
      n -= (n % 1000);
    }

    if (n > 0) {
      /* See what duration the given framerate should be */
      a = gst_util_uint64_scale_int (GST_SECOND, d, n);
      /* Compute absolute error */
      a = (a < duration) ? (duration - a) : (a - duration);
      if (a < 2) {
        /* Really precise - take this option */
        if (dest_n)
          *dest_n = n;
        if (dest_d)
          *dest_d = d;
        return TRUE;
      }
      /* If within 0.1%, remember this denominator */
      if (a * 1000 < duration && a < best_error) {
        best_error = a;
        best_n = n;
        best_d = d;
      }
    }
  }

  /* set results */
  gcd = gst_util_greatest_common_divisor (best_n, best_d);
  if (gcd) {
    best_n /= gcd;
    best_d /= gcd;
  }
  if (dest_n)
    *dest_n = best_n;
  if (dest_d)
    *dest_d = best_d;

  return (best_error != G_MAXUINT64);
}
gboolean
moov_recov_write_file (MoovRecovFile * moovrf, MdatRecovFile * mdatrf,
    FILE * outf, GError ** err)
{
  guint8 auxdata[16];
  guint8 *data = NULL;
  guint8 *prefix_data = NULL;
  guint8 *mvhd_data = NULL;
  guint8 *trak_data = NULL;
  guint32 moov_size = 0;
  gint i;
  guint64 stbl_children_size = 0;
  guint8 *stbl_children = NULL;
  guint32 longest_duration = 0;
  guint16 version;

  /* check the version */
  if (fseek (moovrf->file, 0, SEEK_SET) != 0) {
    g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
        "Failed to seek to the start of the moov recovery file");
    goto fail;
  }
  if (fread (auxdata, 1, 2, moovrf->file) != 2) {
    g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
        "Failed to read version from file");
  }

  version = GST_READ_UINT16_BE (auxdata);
  if (version != ATOMS_RECOV_FILE_VERSION) {
    g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_VERSION,
        "Input file version (%u) is not supported in this version (%u)",
        version, ATOMS_RECOV_FILE_VERSION);
    return FALSE;
  }

  /* write the ftyp */
  prefix_data = g_malloc (moovrf->prefix_size);
  if (fread (prefix_data, 1, moovrf->prefix_size,
          moovrf->file) != moovrf->prefix_size) {
    g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
        "Failed to read the ftyp atom from file");
    goto fail;
  }
  if (fwrite (prefix_data, 1, moovrf->prefix_size, outf) != moovrf->prefix_size) {
    ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
    goto fail;
  }
  g_free (prefix_data);
  prefix_data = NULL;

  /* need to calculate the moov size beforehand to add the offset to
   * chunk offset entries */
  moov_size += moovrf->mvhd_size + 8;   /* mvhd + moov size + fourcc */
  for (i = 0; i < moovrf->num_traks; i++) {
    TrakRecovData *trak = &(moovrf->traks_rd[i]);
    guint32 duration;           /* in moov's timescale */
    guint32 trak_size;

    /* convert trak duration to moov's duration */
    duration = gst_util_uint64_scale_round (trak->duration, moovrf->timescale,
        trak->timescale);

    if (duration > longest_duration)
      longest_duration = duration;
    trak_size = trak_recov_data_get_trak_atom_size (trak);
    if (trak_size == 0) {
      g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_GENERIC,
          "Failed to estimate trak atom size");
      goto fail;
    }
    moov_size += trak_size;
  }

  /* add chunks offsets */
  for (i = 0; i < moovrf->num_traks; i++) {
    TrakRecovData *trak = &(moovrf->traks_rd[i]);
    /* 16 for the mdat header */
    gint64 offset = moov_size + ftell (outf) + 16;
    atom_stco64_chunks_add_offset (&trak->stbl.stco64, offset);
  }

  /* write the moov */
  GST_WRITE_UINT32_BE (auxdata, moov_size);
  GST_WRITE_UINT32_LE (auxdata + 4, FOURCC_moov);
  if (fwrite (auxdata, 1, 8, outf) != 8) {
    ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
    goto fail;
  }

  /* write the mvhd */
  mvhd_data = g_malloc (moovrf->mvhd_size);
  if (fseek (moovrf->file, moovrf->mvhd_pos, SEEK_SET) != 0)
    goto fail;
  if (fread (mvhd_data, 1, moovrf->mvhd_size,
          moovrf->file) != moovrf->mvhd_size)
    goto fail;
  GST_WRITE_UINT32_BE (mvhd_data + 20, moovrf->timescale);
  GST_WRITE_UINT32_BE (mvhd_data + 24, longest_duration);
  if (fwrite (mvhd_data, 1, moovrf->mvhd_size, outf) != moovrf->mvhd_size) {
    ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
    goto fail;
  }
  g_free (mvhd_data);
  mvhd_data = NULL;

  /* write the traks, this is the tough part because we need to update:
   * - stbl atom
   * - sizes of atoms from stbl to trak
   * - trak duration
   */
  for (i = 0; i < moovrf->num_traks; i++) {
    TrakRecovData *trak = &(moovrf->traks_rd[i]);
    guint trak_data_size;
    guint32 stbl_new_size;
    guint32 minf_new_size;
    guint32 mdia_new_size;
    guint32 trak_new_size;
    guint32 size_diff;
    guint32 duration;           /* in moov's timescale */

    /* convert trak duration to moov's duration */
    duration = gst_util_uint64_scale_round (trak->duration, moovrf->timescale,
        trak->timescale);

    stbl_children = moov_recov_get_stbl_children_data (moovrf, trak,
        &stbl_children_size);
    if (stbl_children == NULL)
      goto fail;

    /* calc the new size of the atoms from stbl to trak in the atoms tree */
    stbl_new_size = trak->stsd_size + stbl_children_size + 8;
    size_diff = stbl_new_size - trak->stbl_size;
    minf_new_size = trak->minf_size + size_diff;
    mdia_new_size = trak->mdia_size + size_diff;
    trak_new_size = trak->trak_size + size_diff;

    if (fseek (moovrf->file, trak->file_offset, SEEK_SET) != 0)
      goto fail;
    trak_data_size = trak->post_stsd_offset - trak->file_offset;
    trak_data = g_malloc (trak_data_size);
    if (fread (trak_data, 1, trak_data_size, moovrf->file) != trak_data_size) {
      goto fail;
    }
    /* update the size values in those read atoms before writing */
    GST_WRITE_UINT32_BE (trak_data, trak_new_size);
    GST_WRITE_UINT32_BE (trak_data + (trak->mdia_file_offset -
            trak->file_offset), mdia_new_size);
    GST_WRITE_UINT32_BE (trak_data + (trak->minf_file_offset -
            trak->file_offset), minf_new_size);
    GST_WRITE_UINT32_BE (trak_data + (trak->stbl_file_offset -
            trak->file_offset), stbl_new_size);

    /* update duration values in tkhd and mdhd */
    GST_WRITE_UINT32_BE (trak_data + (trak->tkhd_file_offset -
            trak->file_offset) + 28, duration);
    GST_WRITE_UINT32_BE (trak_data + (trak->mdhd_file_offset -
            trak->file_offset) + 24, trak->duration);

    if (fwrite (trak_data, 1, trak_data_size, outf) != trak_data_size) {
      ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
      goto fail;
    }
    if (fwrite (stbl_children, 1, stbl_children_size, outf) !=
        stbl_children_size) {
      ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
      goto fail;
    }
    g_free (trak_data);
    trak_data = NULL;
    g_free (stbl_children);
    stbl_children = NULL;
  }

  /* write the mdat */
  /* write the header first */
  GST_WRITE_UINT32_BE (auxdata, 1);
  GST_WRITE_UINT32_LE (auxdata + 4, FOURCC_mdat);
  GST_WRITE_UINT64_BE (auxdata + 8, mdatrf->mdat_size);
  if (fwrite (auxdata, 1, 16, outf) != 16) {
    ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
    goto fail;
  }

  /* now read the mdat data and output to the file */
  if (fseek (mdatrf->file, mdatrf->mdat_start +
          (mdatrf->rawfile ? 0 : mdatrf->mdat_header_size), SEEK_SET) != 0)
    goto fail;

  data = g_malloc (4096);
  while (!feof (mdatrf->file)) {
    gint read, write;

    read = fread (data, 1, 4096, mdatrf->file);
    write = fwrite (data, 1, read, outf);

    if (write != read) {
      g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
          "Failed to copy data to output file: %s", g_strerror (errno));
      goto fail;
    }
  }
  g_free (data);

  return TRUE;

fail:
  g_free (stbl_children);
  g_free (mvhd_data);
  g_free (prefix_data);
  g_free (trak_data);
  g_free (data);
  return FALSE;
}