diff --git a/librmff/librmff.h b/librmff/librmff.h index 844f88dab..ce7c40d66 100644 --- a/librmff/librmff.h +++ b/librmff/librmff.h @@ -184,6 +184,25 @@ extern "C" { \link ::rmff_prop_t PROP header\endlink. */ #define RMFF_FILE_FLAG_DOWNLOAD_ENABLED 0x0008 +/** \brief The common object handler. It precedes all the other headers. + */ +typedef struct rmff_object_t { + /** \brief The object's id, e.g. \c 'PROP'. */ + uint32_t id; + /** \brief The size of this header including this object header. */ + uint32_t size; + /** \brief The version, usually 0. */ + uint16_t version; +} rmff_object_t; + +/** \brief The main file header. It is located at the very beginning of + the file. */ +typedef struct rmff_rmf_t { + rmff_object_t obj; + uint32_t format_version; + uint32_t num_headers; +} rmff_rmf_t; + /** \brief The global PROP file header. This header is mandatory for a RealMedia file. It contains statistical @@ -193,6 +212,7 @@ extern "C" { ::rmff_put_uint32_be for accessing the members. */ typedef struct rmff_prop_t { + rmff_object_t obj; uint32_t max_bit_rate; uint32_t avg_bit_rate; uint32_t max_packet_size; @@ -213,6 +233,7 @@ typedef struct rmff_prop_t { ::rmff_set_cont_header must be used instead. */ typedef struct rmff_cont_t { + rmff_object_t obj; char *title; char *author; char *copyright; @@ -228,6 +249,7 @@ typedef struct rmff_cont_t { ::rmff_put_uint32_be for accessing the members. */ typedef struct rmff_mdpr_t { + rmff_object_t obj; /** \brief The track number. It is unique regarding the file. */ uint16_t id; /** \brief The maximum bitrate in bits/second. @@ -406,6 +428,7 @@ typedef struct rmff_file_t { int headers_read; + rmff_rmf_t rmf_header; rmff_prop_t prop_header; rmff_cont_t cont_header; int cont_header_present; diff --git a/librmff/rmff.c b/librmff/rmff.c index 3b140a02d..6473144d5 100644 --- a/librmff/rmff.c +++ b/librmff/rmff.c @@ -167,7 +167,8 @@ file_read_uint8(mb_file_io_t *io, void *fh) { unsigned char tmp; - io->read(fh, &tmp, 1); + if (io->read(fh, &tmp, 1) != 1) + return set_error(RMFF_ERR_IO, NULL, 0); return tmp; } @@ -176,7 +177,8 @@ file_read_uint16_be(mb_file_io_t *io, void *fh) { unsigned char tmp[2]; - io->read(fh, tmp, 2); + if (io->read(fh, tmp, 2) != 2) + return set_error(RMFF_ERR_IO, NULL, 0); return rmff_get_uint16_be(tmp); } @@ -185,7 +187,8 @@ file_read_uint32_be(mb_file_io_t *io, void *fh) { unsigned char tmp[4]; - io->read(fh, tmp, 4); + if (io->read(fh, tmp, 4) != 4) + return set_error(RMFF_ERR_IO, NULL, 0); return rmff_get_uint32_be(tmp); } @@ -503,6 +506,7 @@ rmff_read_headers(rmff_file_t *file) { void *fh; uint32_t object_id, object_size, size; uint16_t object_version; + rmff_rmf_t *rmf; rmff_prop_t *prop; rmff_cont_t *cont; rmff_mdpr_t *mdpr; @@ -521,13 +525,19 @@ rmff_read_headers(rmff_file_t *file) { io = file->io; fh = file->handle; fint = (rmff_file_internal_t *)file->internal; - if (io->seek(fh, 4, SEEK_SET)) + if (io->seek(fh, 0, SEEK_SET)) return set_error(RMFF_ERR_IO, NULL, -1); - skip(4); /* header_size */ - skip(2); /* object_version */ - skip(4); /* file_version */ - skip(4); /* num_headers */ + rmf = &file->rmf_header; + + rmff_last_error = RMFF_ERR_OK; + read_uint32_be_to(&rmf->obj.id); + read_uint32_be_to(&rmf->obj.size); + read_uint16_be_to(&rmf->obj.version); + read_uint32_be_to(&rmf->format_version); + read_uint32_be_to(&rmf->num_headers); + if (rmff_last_error != RMFF_ERR_OK) + return rmff_last_error; prop = &file->prop_header; prop_header_found = 0; @@ -541,6 +551,9 @@ rmff_read_headers(rmff_file_t *file) { break; if (object_id == rmffFOURCC('P', 'R', 'O', 'P')) { + rmff_put_uint32_be(&prop->obj.id, object_id); + rmff_put_uint32_be(&prop->obj.size, object_size); + rmff_put_uint16_be(&prop->obj.version, object_version); read_uint32_be_to(&prop->max_bit_rate); read_uint32_be_to(&prop->avg_bit_rate); read_uint32_be_to(&prop->max_packet_size); @@ -562,6 +575,9 @@ rmff_read_headers(rmff_file_t *file) { safefree(cont->comment); } memset(cont, 0, sizeof(rmff_cont_t)); + rmff_put_uint32_be(&cont->obj.id, object_id); + rmff_put_uint32_be(&cont->obj.size, object_size); + rmff_put_uint16_be(&cont->obj.version, object_version); size = read_uint16_be(); /* title_len */ if (size > 0) { @@ -589,6 +605,9 @@ rmff_read_headers(rmff_file_t *file) { track = (rmff_track_t *)safecalloc(sizeof(rmff_track_t)); track->file = (struct rmff_file_t *)file; mdpr = &track->mdpr_header; + rmff_put_uint32_be(&mdpr->obj.id, object_id); + rmff_put_uint32_be(&mdpr->obj.size, object_size); + rmff_put_uint16_be(&mdpr->obj.version, object_version); read_uint16_be_to(&mdpr->id); track->id = rmff_get_uint16_be(&mdpr->id); read_uint32_be_to(&mdpr->max_bit_rate);