atomsrecovery: read from mdat only what is on headers

It is possible that the mdat has more data than what was stored in the
headers file. If we put that to the output the file will have bogus data
at the end and some players will complain.

https://bugzilla.gnome.org/show_bug.cgi?id=784258
This commit is contained in:
Thiago Santos 2017-07-08 22:11:49 -07:00
parent 69605b6c61
commit 923b83a48c
3 changed files with 31 additions and 7 deletions

View file

@ -88,6 +88,8 @@
#include "atomsrecovery.h"
#define MAX_CHUNK_SIZE (1024 * 1024) /* 1MB */
#define ATOMS_RECOV_OUTPUT_WRITE_ERROR(err) \
g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE, \
"Failed to write to output file: %s", g_strerror (errno))
@ -956,7 +958,7 @@ fail:
gboolean
moov_recov_write_file (MoovRecovFile * moovrf, MdatRecovFile * mdatrf,
FILE * outf, GError ** err)
FILE * outf, GError ** err, GError ** warn)
{
guint8 auxdata[16];
guint8 *data = NULL;
@ -969,6 +971,7 @@ moov_recov_write_file (MoovRecovFile * moovrf, MdatRecovFile * mdatrf,
guint8 *stbl_children = NULL;
guint32 longest_duration = 0;
guint16 version;
guint remaining;
/* check the version */
if (fseek (moovrf->file, 0, SEEK_SET) != 0) {
@ -1159,12 +1162,16 @@ moov_recov_write_file (MoovRecovFile * moovrf, MdatRecovFile * mdatrf,
(mdatrf->rawfile ? 0 : mdatrf->mdat_header_size), SEEK_SET) != 0)
goto fail;
data = g_malloc (4096);
while (!feof (mdatrf->file)) {
gint read, write;
remaining = mdatrf->mdat_size - mdatrf->mdat_header_size;
data = g_malloc (MAX_CHUNK_SIZE);
while (!feof (mdatrf->file) && remaining > 0) {
gint read, write, readsize;
read = fread (data, 1, 4096, mdatrf->file);
readsize = MIN (MAX_CHUNK_SIZE, remaining);
read = fread (data, 1, readsize, mdatrf->file);
write = fwrite (data, 1, read, outf);
remaining -= read;
if (write != read) {
g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
@ -1174,6 +1181,17 @@ moov_recov_write_file (MoovRecovFile * moovrf, MdatRecovFile * mdatrf,
}
g_free (data);
if (remaining) {
g_set_error (warn, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
"Samples in recovery file were not present on headers."
" Bytes lost: %u", remaining);
} else if (!feof (mdatrf->file)) {
g_set_error (warn, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
"Samples in headers were not found in data file.");
GST_FIXME ("Rewrite mdat size if we reach this to make the file"
" fully correct");
}
return TRUE;
fail:

View file

@ -157,6 +157,6 @@ gboolean moov_recov_parse_buffers (MoovRecovFile * moovrf,
GError ** err);
gboolean moov_recov_write_file (MoovRecovFile * moovrf,
MdatRecovFile * mdatrf, FILE * outf,
GError ** err);
GError ** err, GError ** warn);
#endif /* __ATOMS_RECOVERY_H__ */

View file

@ -169,6 +169,7 @@ gst_qt_moov_recover_run (void *data)
MoovRecovFile *moov_recov = NULL;
GstQTMoovRecover *qtmr = GST_QT_MOOV_RECOVER_CAST (data);
GError *err = NULL;
GError *warn = NULL;
GST_LOG_OBJECT (qtmr, "Starting task");
@ -243,10 +244,15 @@ gst_qt_moov_recover_run (void *data)
}
GST_DEBUG_OBJECT (qtmr, "Writing fixed file to output");
if (!moov_recov_write_file (moov_recov, mdat_recov, output, &err)) {
if (!moov_recov_write_file (moov_recov, mdat_recov, output, &err, &warn)) {
goto end;
}
if (warn) {
GST_ELEMENT_WARNING (qtmr, RESOURCE, FAILED, ("%s", warn->message), (NULL));
g_error_free (warn);
}
/* here means success */
GST_DEBUG_OBJECT (qtmr, "Finished successfully, posting EOS");
gst_element_post_message (GST_ELEMENT_CAST (qtmr),