Пример #1
0
static void
gst_qt_moov_recover_run (void *data)
{
  FILE *moovrec = NULL;
  FILE *mdatinput = NULL;
  FILE *output = NULL;
  MdatRecovFile *mdat_recov = NULL;
  MoovRecovFile *moov_recov = NULL;
  GstQTMoovRecover *qtmr = GST_QT_MOOV_RECOVER_CAST (data);
  GError *err = NULL;

  GST_LOG_OBJECT (qtmr, "Starting task");

  GST_DEBUG_OBJECT (qtmr, "Validating properties");
  GST_OBJECT_LOCK (qtmr);
  /* validate properties */
  if (qtmr->broken_input == NULL) {
    GST_OBJECT_UNLOCK (qtmr);
    GST_ELEMENT_ERROR (qtmr, RESOURCE, SETTINGS,
        ("Please set broken-input property"), (NULL));
    goto end;
  }
  if (qtmr->recovery_input == NULL) {
    GST_OBJECT_UNLOCK (qtmr);
    GST_ELEMENT_ERROR (qtmr, RESOURCE, SETTINGS,
        ("Please set recovery-input property"), (NULL));
    goto end;
  }
  if (qtmr->fixed_output == NULL) {
    GST_OBJECT_UNLOCK (qtmr);
    GST_ELEMENT_ERROR (qtmr, RESOURCE, SETTINGS,
        ("Please set fixed-output property"), (NULL));
    goto end;
  }

  GST_DEBUG_OBJECT (qtmr, "Opening input/output files");
  /* open files */
  moovrec = g_fopen (qtmr->recovery_input, "rb");
  if (moovrec == NULL) {
    GST_OBJECT_UNLOCK (qtmr);
    GST_ELEMENT_ERROR (qtmr, RESOURCE, OPEN_READ,
        ("Failed to open recovery-input file"), (NULL));
    goto end;
  }

  mdatinput = g_fopen (qtmr->broken_input, "rb");
  if (mdatinput == NULL) {
    GST_OBJECT_UNLOCK (qtmr);
    GST_ELEMENT_ERROR (qtmr, RESOURCE, OPEN_READ,
        ("Failed to open broken-input file"), (NULL));
    goto end;
  }
  output = g_fopen (qtmr->fixed_output, "wb+");
  if (output == NULL) {
    GST_OBJECT_UNLOCK (qtmr);
    GST_ELEMENT_ERROR (qtmr, RESOURCE, OPEN_READ_WRITE,
        ("Failed to open fixed-output file"), (NULL));
    goto end;
  }
  GST_OBJECT_UNLOCK (qtmr);

  GST_DEBUG_OBJECT (qtmr, "Parsing input files");
  /* now create our structures */
  mdat_recov = mdat_recov_file_create (mdatinput, qtmr->faststart_mode, &err);
  mdatinput = NULL;
  if (mdat_recov == NULL) {
    GST_ELEMENT_ERROR (qtmr, RESOURCE, FAILED,
        ("Broken file could not be parsed correctly"), (NULL));
    goto end;
  }
  moov_recov = moov_recov_file_create (moovrec, &err);
  moovrec = NULL;
  if (moov_recov == NULL) {
    GST_ELEMENT_ERROR (qtmr, RESOURCE, FAILED,
        ("Recovery file could not be parsed correctly"), (NULL));
    goto end;
  }

  /* now parse the buffers data from moovrec */
  if (!moov_recov_parse_buffers (moov_recov, mdat_recov, &err)) {
    goto end;
  }

  GST_DEBUG_OBJECT (qtmr, "Writing fixed file to output");
  if (!moov_recov_write_file (moov_recov, mdat_recov, output, &err)) {
    goto end;
  }

  /* here means success */
  GST_DEBUG_OBJECT (qtmr, "Finished successfully, posting EOS");
  gst_element_post_message (GST_ELEMENT_CAST (qtmr),
      gst_message_new_eos (GST_OBJECT_CAST (qtmr)));

end:
  GST_LOG_OBJECT (qtmr, "Finalizing task");
  if (err) {
    GST_ELEMENT_ERROR (qtmr, RESOURCE, FAILED, ("%s", err->message), (NULL));
    g_error_free (err);
  }

  if (moov_recov)
    moov_recov_file_free (moov_recov);
  if (moovrec)
    fclose (moovrec);

  if (mdat_recov)
    mdat_recov_file_free (mdat_recov);
  if (mdatinput)
    fclose (mdatinput);

  if (output)
    fclose (output);
  GST_LOG_OBJECT (qtmr, "Leaving task");
  gst_task_stop (qtmr->task);
}
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;
}