static gboolean
moov_recov_file_parse_prefix (MoovRecovFile * moovrf)
{
  guint32 fourcc;
  guint32 size;
  guint32 total_size = 0;
  if (fseek (moovrf->file, 2, SEEK_SET) != 0)
    return FALSE;
  if (!read_atom_header (moovrf->file, &fourcc, &size)) {
    return FALSE;
  }

  if (fourcc != FOURCC_ftyp) {
    /* we might have a prefix here */
    if (fseek (moovrf->file, size - 8, SEEK_CUR) != 0)
      return FALSE;

    total_size += size;

    /* now read the ftyp */
    if (!read_atom_header (moovrf->file, &fourcc, &size))
      return FALSE;
  }

  /* this has to be the ftyp */
  if (fourcc != FOURCC_ftyp)
    return FALSE;
  total_size += size;
  moovrf->prefix_size = total_size;
  return fseek (moovrf->file, size - 8, SEEK_CUR) == 0;
}
static gboolean
moov_recov_parse_stbl (MoovRecovFile * moovrf, TrakRecovData * trakrd)
{
  guint32 size;
  guint32 fourcc;
  guint32 auxsize;

  if (!read_atom_header (moovrf->file, &fourcc, &size))
    return FALSE;
  if (fourcc != FOURCC_stbl)
    return FALSE;

  trakrd->stbl_file_offset = ftell (moovrf->file) - 8;
  trakrd->stbl_size = size;

  /* skip the stsd */
  if (!read_atom_header (moovrf->file, &fourcc, &auxsize))
    return FALSE;
  if (fourcc != FOURCC_stsd)
    return FALSE;
  if (fseek (moovrf->file, auxsize - 8, SEEK_CUR) != 0)
    return FALSE;

  trakrd->stsd_size = auxsize;
  trakrd->post_stsd_offset = ftell (moovrf->file);

  /* as this is the last atom we parse, we don't skip forward */

  return TRUE;
}
static gboolean
moov_recov_parse_trak (MoovRecovFile * moovrf, TrakRecovData * trakrd)
{
  guint64 offset;
  guint32 size;
  guint32 fourcc;

  offset = ftell (moovrf->file);
  if (offset == -1) {
    return FALSE;
  }

  /* make sure we are on a trak atom */
  if (!read_atom_header (moovrf->file, &fourcc, &size)) {
    return FALSE;
  }
  if (fourcc != FOURCC_trak) {
    return FALSE;
  }
  trakrd->trak_size = size;

  /* now we should have a trak header 'tkhd' */
  if (!moov_recov_parse_tkhd (moovrf, trakrd))
    return FALSE;

  /* FIXME add edts handling here and in qtmux, as this is only detected
   * after buffers start flowing */

  if (!moov_recov_parse_mdia (moovrf, trakrd))
    return FALSE;

  trakrd->file_offset = offset;
  /* position after the trak */
  return fseek (moovrf->file, (long int) offset + size, SEEK_SET) == 0;
}
static gboolean
moov_recov_parse_mdhd (MoovRecovFile * moovrf, TrakRecovData * trakrd)
{
  guint32 size;
  guint32 fourcc;
  guint8 data[4];

  /* make sure we are on a tkhd atom */
  if (!read_atom_header (moovrf->file, &fourcc, &size))
    return FALSE;
  if (fourcc != FOURCC_mdhd)
    return FALSE;

  trakrd->mdhd_file_offset = ftell (moovrf->file) - 8;

  /* get the timescale */
  if (fseek (moovrf->file, 12, SEEK_CUR) != 0)
    return FALSE;
  if (fread (data, 1, 4, moovrf->file) != 4)
    return FALSE;
  trakrd->timescale = GST_READ_UINT32_BE (data);
  if (fseek (moovrf->file, 8, SEEK_CUR) != 0)
    return FALSE;
  return TRUE;
}
static gboolean
moov_recov_parse_tkhd (MoovRecovFile * moovrf, TrakRecovData * trakrd)
{
  guint32 size;
  guint32 fourcc;
  guint8 data[4];

  /* make sure we are on a tkhd atom */
  if (!read_atom_header (moovrf->file, &fourcc, &size))
    return FALSE;
  if (fourcc != FOURCC_tkhd)
    return FALSE;

  trakrd->tkhd_file_offset = ftell (moovrf->file) - 8;

  /* move 8 bytes forward to the trak_id pos */
  if (fseek (moovrf->file, 12, SEEK_CUR) != 0)
    return FALSE;
  if (fread (data, 1, 4, moovrf->file) != 4)
    return FALSE;

  /* advance the rest of tkhd */
  fseek (moovrf->file, 68, SEEK_CUR);

  trakrd->trak_id = GST_READ_UINT32_BE (data);
  return TRUE;
}
static gboolean
moov_recov_parse_minf (MoovRecovFile * moovrf, TrakRecovData * trakrd)
{
  guint32 size;
  guint32 fourcc;
  guint32 auxsize;

  if (!read_atom_header (moovrf->file, &fourcc, &size))
    return FALSE;
  if (fourcc != FOURCC_minf)
    return FALSE;

  trakrd->minf_file_offset = ftell (moovrf->file) - 8;
  trakrd->minf_size = size;

  /* skip either of vmhd, smhd, hmhd that might follow */
  if (!read_atom_header (moovrf->file, &fourcc, &auxsize))
    return FALSE;
  if (fourcc != FOURCC_vmhd && fourcc != FOURCC_smhd && fourcc != FOURCC_hmhd &&
      fourcc != FOURCC_gmhd)
    return FALSE;
  if (fseek (moovrf->file, auxsize - 8, SEEK_CUR))
    return FALSE;

  /* skip a possible hdlr and the following dinf */
  if (!read_atom_header (moovrf->file, &fourcc, &auxsize))
    return FALSE;
  if (fourcc == FOURCC_hdlr) {
    if (fseek (moovrf->file, auxsize - 8, SEEK_CUR))
      return FALSE;
    if (!read_atom_header (moovrf->file, &fourcc, &auxsize))
      return FALSE;
  }
  if (fourcc != FOURCC_dinf)
    return FALSE;
  if (fseek (moovrf->file, auxsize - 8, SEEK_CUR))
    return FALSE;

  /* now we are ready to read the stbl */
  if (!moov_recov_parse_stbl (moovrf, trakrd))
    return FALSE;

  return TRUE;
}
static gboolean
skip_atom (MoovRecovFile * moovrf, guint32 expected_fourcc)
{
  guint32 size;
  guint32 fourcc;

  if (!read_atom_header (moovrf->file, &fourcc, &size))
    return FALSE;
  if (fourcc != expected_fourcc)
    return FALSE;

  return (fseek (moovrf->file, size - 8, SEEK_CUR) == 0);
}
static gboolean
moov_recov_file_parse_mvhd (MoovRecovFile * moovrf)
{
  guint32 fourcc;
  guint32 size;
  if (!read_atom_header (moovrf->file, &fourcc, &size)) {
    return FALSE;
  }
  /* check for sanity */
  if (fourcc != FOURCC_mvhd)
    return FALSE;

  moovrf->mvhd_size = size;
  moovrf->mvhd_pos = ftell (moovrf->file) - 8;

  /* skip the remaining of the mvhd in the file */
  return fseek (moovrf->file, size - 8, SEEK_CUR) == 0;
}
static gboolean
mdat_recov_file_parse_mdat_start (MdatRecovFile * mdatrf)
{
  guint32 fourcc, size;

  if (!read_atom_header (mdatrf->file, &fourcc, &size)) {
    return FALSE;
  }
  if (size == 1) {
    mdatrf->mdat_header_size = 16;
    mdatrf->mdat_size = 16;
  } else {
    mdatrf->mdat_header_size = 8;
    mdatrf->mdat_size = 8;
  }
  mdatrf->mdat_start = ftell (mdatrf->file) - 8;

  return fourcc == FOURCC_mdat;
}
Ejemplo n.º 10
0
static gboolean
moov_recov_parse_mdia (MoovRecovFile * moovrf, TrakRecovData * trakrd)
{
  guint32 size;
  guint32 fourcc;

  /* make sure we are on a tkhd atom */
  if (!read_atom_header (moovrf->file, &fourcc, &size))
    return FALSE;
  if (fourcc != FOURCC_mdia)
    return FALSE;

  trakrd->mdia_file_offset = ftell (moovrf->file) - 8;
  trakrd->mdia_size = size;

  if (!moov_recov_parse_mdhd (moovrf, trakrd))
    return FALSE;

  if (!skip_atom (moovrf, FOURCC_hdlr))
    return FALSE;
  if (!moov_recov_parse_minf (moovrf, trakrd))
    return FALSE;
  return TRUE;
}
Ejemplo n.º 11
0
int
ALACDecoder_init(decoders_ALACDecoder *self,
                 PyObject *args, PyObject *kwds)
{
    PyObject *file;
    unsigned atom_size;
    char atom_name[4];
    int got_decoding_parameters = 0;
    int got_seektable = 0;

    self->bitstream = NULL;
    self->mdat_start = NULL;
    self->total_pcm_frames = 0;
    self->read_pcm_frames = 0;
    self->seektable = NULL;
    self->closed = 0;
    self->audiotools_pcm = NULL;

    /*setup some dummy parameters*/
    self->params.block_size = 4096;
    self->params.history_multiplier = 40;
    self->params.initial_history = 10;
    self->params.maximum_K = 14;

    if (!PyArg_ParseTuple(args, "O", &file)) {
        return -1;
    } else {
        Py_INCREF(file);
    }

    self->bitstream = br_open_external(file,
                                       BS_BIG_ENDIAN,
                                       4096,
                                       br_read_python,
                                       bs_setpos_python,
                                       bs_getpos_python,
                                       bs_free_pos_python,
                                       bs_fseek_python,
                                       bs_close_python,
                                       bs_free_python_decref);

    /*walk through atoms*/
    while (read_atom_header(self->bitstream, &atom_size, atom_name)) {
        if (!memcmp(atom_name, "mdat", 4)) {
            /*get mdat atom's starting position*/
            if (self->mdat_start) {
                PyErr_SetString(PyExc_ValueError,
                                "multiple mdat atoms found in stream");
                return -1;
            } else {
                self->mdat_start = self->bitstream->getpos(self->bitstream);
                self->bitstream->seek(self->bitstream,
                                      atom_size - 8,
                                      BS_SEEK_CUR);
            }
        } else if (!memcmp(atom_name, "moov", 4)) {
            /*find and parse metadata from moov atom*/

            struct qt_atom *moov_atom;

            if (!setjmp(*br_try(self->bitstream))) {
                moov_atom = qt_atom_parse_by_name(self->bitstream,
                                                  atom_size,
                                                  atom_name);

                br_etry(self->bitstream);
            } else {
                br_etry(self->bitstream);
                PyErr_SetString(PyExc_IOError, "I/O error parsing moov atom");
                return -1;
            }

            if (!got_decoding_parameters &&
                get_decoding_parameters(self, moov_atom)) {

                /*this is an arbitrary block size limit
                  to keep from blowing up the stack

                  Apple's reference encoder uses 4096 exclusively
                  but the file format allows sizes up to 32 bits(!)
                  which would break the whole world if anybody used
                  them all for a single ALAC frame.

                  so I'll just assume such files are malicious
                  and reject them outright*/
                if (self->params.block_size > 65535) {
                    PyErr_SetString(PyExc_ValueError, "block size too large");
                    return -1;
                }

                got_decoding_parameters = 1;
            }

            if (!got_seektable && get_seektable(self, moov_atom)) {
                got_seektable = 1;
            }

            moov_atom->free(moov_atom);
        } else {
            /*skip remaining atoms*/

            if (atom_size >= 8) {
                self->bitstream->seek(self->bitstream,
                                      atom_size - 8,
                                      BS_SEEK_CUR);
            }
        }
    }

    if (!got_decoding_parameters) {
        PyErr_SetString(PyExc_ValueError, "no decoding parameters");
        return -1;
    }

    /*seek to start of mdat atom*/
    if (self->mdat_start) {
        self->bitstream->setpos(self->bitstream, self->mdat_start);
    } else {
        PyErr_SetString(PyExc_ValueError, "no mdat atom found in stream");
        return -1;
    }

    /*open FrameList generator*/
    if ((self->audiotools_pcm = open_audiotools_pcm()) == NULL) {
        return -1;
    }

    return 0;
}
Ejemplo n.º 12
0
MdatRecovFile *
mdat_recov_file_create (FILE * file, gboolean datafile, GError ** err)
{
  MdatRecovFile *mrf = g_new0 (MdatRecovFile, 1);
  guint32 fourcc, size;

  g_return_val_if_fail (file != NULL, NULL);

  mrf->file = file;
  mrf->rawfile = datafile;

  /* get the file/data length */
  if (fseek (file, 0, SEEK_END) != 0)
    goto file_length_error;
  /* still needs to deduce the mdat header and ftyp size */
  mrf->data_size = ftell (file);
  if (mrf->data_size == -1L)
    goto file_length_error;

  if (fseek (file, 0, SEEK_SET) != 0)
    goto file_seek_error;

  if (datafile) {
    /* this file contains no atoms, only raw data to be placed on the mdat
     * this happens when faststart mode is used */
    mrf->mdat_start = 0;
    mrf->mdat_header_size = 16;
    mrf->mdat_size = 16;
    return mrf;
  }

  if (!read_atom_header (file, &fourcc, &size)) {
    goto parse_error;
  }
  if (fourcc != FOURCC_ftyp) {
    /* this could be a prefix atom, let's skip it and try again */
    if (fseek (file, size - 8, SEEK_CUR) != 0) {
      goto file_seek_error;
    }
    if (!read_atom_header (file, &fourcc, &size)) {
      goto parse_error;
    }
  }

  if (fourcc != FOURCC_ftyp) {
    goto parse_error;
  }
  if (fseek (file, size - 8, SEEK_CUR) != 0)
    goto file_seek_error;

  /* we don't parse this if we have a tmpdatafile */
  if (!mdat_recov_file_parse_mdat_start (mrf)) {
    g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_PARSING,
        "Error while parsing mdat atom");
    goto fail;
  }

  return mrf;

parse_error:
  g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
      "Failed to parse atom");
  goto fail;

file_seek_error:
  g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
      "Failed to seek to start of the file");
  goto fail;

file_length_error:
  g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
      "Failed to determine file size");
  goto fail;

fail:
  mdat_recov_file_free (mrf);
  return NULL;
}