Пример #1
0
/* FIXME: for our purposes it's probably enough to just check for the sync
 * marker - we just want to know if it's a header frame or not */
static gboolean
gst_flac_dec_scan_got_frame (GstFlacDec * flacdec, guint8 * data, guint size,
    gint64 * last_sample_num)
{
  guint headerlen;
  guint sr_from_end = 0;        /* can be 0, 8 or 16 */
  guint bs_from_end = 0;        /* can be 0, 8 or 16 */
  guint32 val = 0;
  guint8 bs, sr, ca, ss, pb;

  if (size < 10)
    return FALSE;

  /* sync */
  if (data[0] != 0xFF || (data[1] & 0xFC) != 0xF8)
    return FALSE;
  if (data[1] & 1) {
    GST_WARNING_OBJECT (flacdec, "Variable block size FLAC unsupported");
    return FALSE;
  }

  bs = (data[2] & 0xF0) >> 4;   /* blocksize marker   */
  sr = (data[2] & 0x0F);        /* samplerate marker  */
  ca = (data[3] & 0xF0) >> 4;   /* channel assignment */
  ss = (data[3] & 0x0F) >> 1;   /* sample size marker */
  pb = (data[3] & 0x01);        /* padding bit        */

  GST_LOG_OBJECT (flacdec,
      "got sync, bs=%x,sr=%x,ca=%x,ss=%x,pb=%x", bs, sr, ca, ss, pb);

  if (bs == 0 || sr == 0x0F || ca >= 0x0B || ss == 0x03 || ss == 0x07) {
    return FALSE;
  }

  /* read block size from end of header? */
  if (bs == 6)
    bs_from_end = 8;
  else if (bs == 7)
    bs_from_end = 16;

  /* read sample rate from end of header? */
  if (sr == 0x0C)
    sr_from_end = 8;
  else if (sr == 0x0D || sr == 0x0E)
    sr_from_end = 16;

  val = data[4];
  /* This is slightly faster than a loop */
  if (!(val & 0x80)) {
    val = 0;
  } else if ((val & 0xc0) && !(val & 0x20)) {
    val = 1;
  } else if ((val & 0xe0) && !(val & 0x10)) {
    val = 2;
  } else if ((val & 0xf0) && !(val & 0x08)) {
    val = 3;
  } else if ((val & 0xf8) && !(val & 0x04)) {
    val = 4;
  } else if ((val & 0xfc) && !(val & 0x02)) {
    val = 5;
  } else if ((val & 0xfe) && !(val & 0x01)) {
    val = 6;
  } else {
    GST_LOG_OBJECT (flacdec, "failed to read sample/frame");
    return FALSE;
  }

  val++;
  headerlen = 4 + val + (bs_from_end / 8) + (sr_from_end / 8);

  if (gst_flac_calculate_crc8 (data, headerlen) != data[headerlen]) {
    GST_LOG_OBJECT (flacdec, "invalid checksum");
    return FALSE;
  }

  if (!last_sample_num)
    return TRUE;

  /* FIXME: This is can be 36 bit if variable block size is used,
   * fortunately not encoder supports this yet and we check for that
   * above.
   */
  val = (guint32) g_utf8_get_char_validated ((gchar *) data + 4, -1);

  if (val == (guint32) - 1 || val == (guint32) - 2) {
    GST_LOG_OBJECT (flacdec, "failed to read sample/frame");
    return FALSE;
  }

  if (flacdec->min_blocksize == flacdec->max_blocksize) {
    *last_sample_num = (val + 1) * flacdec->min_blocksize;
  } else {
    *last_sample_num = 0;       /* FIXME: + length of last block in samples */
  }

  /* FIXME: only valid for fixed block size streams */
  GST_DEBUG_OBJECT (flacdec, "frame number: %" G_GINT64_FORMAT,
      *last_sample_num);

  if (flacdec->info.rate > 0 && *last_sample_num != 0) {
    GST_DEBUG_OBJECT (flacdec, "last sample %" G_GINT64_FORMAT " = %"
        GST_TIME_FORMAT, *last_sample_num,
        GST_TIME_ARGS (*last_sample_num * GST_SECOND / flacdec->info.rate));
  }

  return TRUE;
}
Пример #2
0
/* FIXME: for our purposes it's probably enough to just check for the sync
 * marker - we just want to know if it's a header frame or not */
static gboolean
gst_flac_dec_scan_got_frame (GstFlacDec * flacdec, const guint8 * data,
    guint size)
{
  guint headerlen;
  guint sr_from_end = 0;        /* can be 0, 8 or 16 */
  guint bs_from_end = 0;        /* can be 0, 8 or 16 */
  guint32 val = 0;
  guint8 bs, sr, ca, ss, pb;
  gboolean vbs;

  if (size < 10)
    return FALSE;

  /* sync */
  if (data[0] != 0xFF || (data[1] & 0xFC) != 0xF8)
    return FALSE;

  vbs = ! !(data[1] & 1);       /* variable blocksize */
  bs = (data[2] & 0xF0) >> 4;   /* blocksize marker   */
  sr = (data[2] & 0x0F);        /* samplerate marker  */
  ca = (data[3] & 0xF0) >> 4;   /* channel assignment */
  ss = (data[3] & 0x0F) >> 1;   /* sample size marker */
  pb = (data[3] & 0x01);        /* padding bit        */

  GST_LOG_OBJECT (flacdec,
      "got sync, vbs=%d,bs=%x,sr=%x,ca=%x,ss=%x,pb=%x", vbs, bs, sr, ca, ss,
      pb);

  if (bs == 0 || sr == 0x0F || ca >= 0x0B || ss == 0x03 || ss == 0x07) {
    return FALSE;
  }

  /* read block size from end of header? */
  if (bs == 6)
    bs_from_end = 8;
  else if (bs == 7)
    bs_from_end = 16;

  /* read sample rate from end of header? */
  if (sr == 0x0C)
    sr_from_end = 8;
  else if (sr == 0x0D || sr == 0x0E)
    sr_from_end = 16;

  val = data[4];
  /* This is slightly faster than a loop */
  if (!(val & 0x80)) {
    val = 0;
  } else if ((val & 0xc0) && !(val & 0x20)) {
    val = 1;
  } else if ((val & 0xe0) && !(val & 0x10)) {
    val = 2;
  } else if ((val & 0xf0) && !(val & 0x08)) {
    val = 3;
  } else if ((val & 0xf8) && !(val & 0x04)) {
    val = 4;
  } else if ((val & 0xfc) && !(val & 0x02)) {
    val = 5;
  } else if ((val & 0xfe) && !(val & 0x01)) {
    val = 6;
  } else {
    GST_LOG_OBJECT (flacdec, "failed to read sample/frame");
    return FALSE;
  }

  val++;
  headerlen = 4 + val + (bs_from_end / 8) + (sr_from_end / 8);

  if (gst_flac_calculate_crc8 (data, headerlen) != data[headerlen]) {
    GST_LOG_OBJECT (flacdec, "invalid checksum");
    return FALSE;
  }

  return TRUE;
}