mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-25 04:11:44 +00:00
Merged 1571.
This commit is contained in:
parent
51ced57715
commit
484b0c2fd9
@ -177,14 +177,14 @@ typedef struct rmff_file_t {
|
|||||||
mb_file_io_t *io;
|
mb_file_io_t *io;
|
||||||
void *handle;
|
void *handle;
|
||||||
char *name;
|
char *name;
|
||||||
|
int open_mode;
|
||||||
int64_t size;
|
int64_t size;
|
||||||
|
|
||||||
int headers_read;
|
int headers_read;
|
||||||
|
|
||||||
rmff_prop_t prop_header;
|
rmff_prop_t prop_header;
|
||||||
int prop_header_found;
|
|
||||||
rmff_cont_t cont_header;
|
rmff_cont_t cont_header;
|
||||||
int cont_header_found;
|
int cont_header_present;
|
||||||
int64_t first_data_header_offset;
|
int64_t first_data_header_offset;
|
||||||
int64_t next_data_header_offset;
|
int64_t next_data_header_offset;
|
||||||
uint32_t num_packets_in_chunk;
|
uint32_t num_packets_in_chunk;
|
||||||
@ -269,6 +269,7 @@ void rmff_close_file(rmff_file_t *file);
|
|||||||
int rmff_read_headers(rmff_file_t *file);
|
int rmff_read_headers(rmff_file_t *file);
|
||||||
|
|
||||||
/** \brief Retrieves the size of the next frame.
|
/** \brief Retrieves the size of the next frame.
|
||||||
|
*
|
||||||
* \param file The file to read from.
|
* \param file The file to read from.
|
||||||
* \returns the size of the following frame or one of the \c RMFF_ERR_*
|
* \returns the size of the following frame or one of the \c RMFF_ERR_*
|
||||||
* constants on error.
|
* constants on error.
|
||||||
@ -277,6 +278,7 @@ int rmff_get_next_frame_size(rmff_file_t *file);
|
|||||||
|
|
||||||
/** \brief Reads the next frame from the file.
|
/** \brief Reads the next frame from the file.
|
||||||
* The frame must be released by rmff_release_frame(rmff_frame_t*).
|
* The frame must be released by rmff_release_frame(rmff_frame_t*).
|
||||||
|
*
|
||||||
* \param file The file to read from.
|
* \param file The file to read from.
|
||||||
* \param buffer A buffer to read the frame into. This parameter may be
|
* \param buffer A buffer to read the frame into. This parameter may be
|
||||||
* \c NULL in which case the buffer will be allocated by the library.
|
* \c NULL in which case the buffer will be allocated by the library.
|
||||||
@ -290,11 +292,26 @@ rmff_frame_t *rmff_read_next_frame(rmff_file_t *file, void *buffer);
|
|||||||
|
|
||||||
/** \brief Frees all resources associated with a frame.
|
/** \brief Frees all resources associated with a frame.
|
||||||
* If the frame buffer was allocated by the library it will be freed as well.
|
* If the frame buffer was allocated by the library it will be freed as well.
|
||||||
|
*
|
||||||
* \param frame The frame to free.
|
* \param frame The frame to free.
|
||||||
*/
|
*/
|
||||||
void rmff_release_frame(rmff_frame_t *frame);
|
void rmff_release_frame(rmff_frame_t *frame);
|
||||||
|
|
||||||
|
/** \brief Sets the contents of the CONT file header.
|
||||||
|
* Frees the old contents if any and allocates copies of the given
|
||||||
|
* strings. If the CONT header should be written to the file
|
||||||
|
* in rmff_write_headers(rmff_file_t*) then the \c cont_header_found
|
||||||
|
* member must be set to 1.
|
||||||
|
*
|
||||||
|
* \param file The file whose CONT header should be set.
|
||||||
|
* \param title The file's title, e.g. "Muriel's Wedding"
|
||||||
|
* \param author The file's author, e.g. "P.J. Hogan"
|
||||||
|
* \param copyright The copyright assigned to the file.
|
||||||
|
* \param comment A free-style comment.
|
||||||
|
*/
|
||||||
|
void rmff_set_cont_header(rmff_file_t *file, const char *title,
|
||||||
|
const char *author, const char *copyright,
|
||||||
|
const char *comment);
|
||||||
|
|
||||||
/** \brief The error code of the last function call.
|
/** \brief The error code of the last function call.
|
||||||
* Contains the last error code for a function that failed. If a function
|
* Contains the last error code for a function that failed. If a function
|
||||||
|
111
librmff/rmff.c
111
librmff/rmff.c
@ -242,35 +242,20 @@ _saferealloc(void *mem,
|
|||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
rmff_file_t *
|
static rmff_file_t *
|
||||||
rmff_open_file(const char *path,
|
open_file_for_reading(const char *path,
|
||||||
int mode) {
|
|
||||||
return rmff_open_file_with_io(path, mode, &std_mb_file_io);
|
|
||||||
}
|
|
||||||
|
|
||||||
rmff_file_t *
|
|
||||||
rmff_open_file_with_io(const char *path,
|
|
||||||
int mode,
|
|
||||||
mb_file_io_t *io) {
|
mb_file_io_t *io) {
|
||||||
rmff_file_t *file;
|
rmff_file_t *file;
|
||||||
void *file_h;
|
void *file_h;
|
||||||
char buf[5];
|
char signature[5];
|
||||||
|
|
||||||
if ((path == NULL) || (io == NULL) ||
|
file_h = io->open(path, MB_OPEN_MODE_READING);
|
||||||
((mode != RMFF_OPEN_MODE_READING) && (mode != RMFF_OPEN_MODE_WRITING)))
|
|
||||||
return (rmff_file_t *)set_error(RMFF_ERR_PARAMETERS, NULL, 0);
|
|
||||||
|
|
||||||
if (mode == RMFF_OPEN_MODE_READING)
|
|
||||||
mode = MB_OPEN_MODE_READING;
|
|
||||||
else
|
|
||||||
mode = MB_OPEN_MODE_WRITING;
|
|
||||||
file_h = io->open(path, mode);
|
|
||||||
if (file_h == NULL)
|
if (file_h == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
buf[4] = 0;
|
signature[4] = 0;
|
||||||
if ((io->read(file_h, buf, 4) != 4) ||
|
if ((io->read(file_h, signature, 4) != 4) ||
|
||||||
strcmp(buf, ".RMF")) {
|
strcmp(signature, ".RMF")) {
|
||||||
io->close(file_h);
|
io->close(file_h);
|
||||||
return (rmff_file_t *)set_error(RMFF_ERR_NOT_RMFF, NULL, 0);
|
return (rmff_file_t *)set_error(RMFF_ERR_NOT_RMFF, NULL, 0);
|
||||||
}
|
}
|
||||||
@ -282,10 +267,57 @@ rmff_open_file_with_io(const char *path,
|
|||||||
io->seek(file_h, 0, SEEK_END);
|
io->seek(file_h, 0, SEEK_END);
|
||||||
file->size = io->tell(file_h);
|
file->size = io->tell(file_h);
|
||||||
io->seek(file_h, 4, SEEK_SET);
|
io->seek(file_h, 4, SEEK_SET);
|
||||||
|
file->open_mode = RMFF_OPEN_MODE_READING;
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static rmff_file_t *
|
||||||
|
open_file_for_writing(const char *path,
|
||||||
|
mb_file_io_t *io) {
|
||||||
|
rmff_file_t *file;
|
||||||
|
void *file_h;
|
||||||
|
const char *signature = ".RMF";
|
||||||
|
|
||||||
|
file_h = io->open(path, MB_OPEN_MODE_WRITING);
|
||||||
|
if (file_h == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (io->write(file_h, signature, 4) != 4) {
|
||||||
|
io->close(file_h);
|
||||||
|
return (rmff_file_t *)set_error(RMFF_ERR_IO, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
file = (rmff_file_t *)safecalloc(sizeof(rmff_file_t));
|
||||||
|
file->handle = file_h;
|
||||||
|
file->name = safestrdup(path);
|
||||||
|
file->io = io;
|
||||||
|
file->size = -1;
|
||||||
|
file->open_mode = RMFF_OPEN_MODE_WRITING;
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
rmff_file_t *
|
||||||
|
rmff_open_file(const char *path,
|
||||||
|
int mode) {
|
||||||
|
return rmff_open_file_with_io(path, mode, &std_mb_file_io);
|
||||||
|
}
|
||||||
|
|
||||||
|
rmff_file_t *
|
||||||
|
rmff_open_file_with_io(const char *path,
|
||||||
|
int mode,
|
||||||
|
mb_file_io_t *io) {
|
||||||
|
if ((path == NULL) || (io == NULL) ||
|
||||||
|
((mode != RMFF_OPEN_MODE_READING) && (mode != RMFF_OPEN_MODE_WRITING)))
|
||||||
|
return (rmff_file_t *)set_error(RMFF_ERR_PARAMETERS, NULL, 0);
|
||||||
|
|
||||||
|
if (mode == RMFF_OPEN_MODE_READING)
|
||||||
|
return open_file_for_reading(path, io);
|
||||||
|
else
|
||||||
|
return open_file_for_writing(path, io);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rmff_free_track_data(rmff_track_t *track) {
|
rmff_free_track_data(rmff_track_t *track) {
|
||||||
if (track == NULL)
|
if (track == NULL)
|
||||||
@ -330,8 +362,9 @@ rmff_read_headers(rmff_file_t *file) {
|
|||||||
rmff_track_t track;
|
rmff_track_t track;
|
||||||
real_video_props_t *rvp;
|
real_video_props_t *rvp;
|
||||||
real_audio_v4_props_t *ra4p;
|
real_audio_v4_props_t *ra4p;
|
||||||
|
int prop_header_found;
|
||||||
|
|
||||||
if (file == NULL)
|
if ((file == NULL) || (file->open_mode != RMFF_OPEN_MODE_READING))
|
||||||
return set_error(RMFF_ERR_PARAMETERS, NULL, RMFF_ERR_PARAMETERS);
|
return set_error(RMFF_ERR_PARAMETERS, NULL, RMFF_ERR_PARAMETERS);
|
||||||
if (file->headers_read)
|
if (file->headers_read)
|
||||||
return 0;
|
return 0;
|
||||||
@ -347,6 +380,7 @@ rmff_read_headers(rmff_file_t *file) {
|
|||||||
skip(4); /* num_headers */
|
skip(4); /* num_headers */
|
||||||
|
|
||||||
prop = &file->prop_header;
|
prop = &file->prop_header;
|
||||||
|
prop_header_found = 0;
|
||||||
cont = &file->cont_header;
|
cont = &file->cont_header;
|
||||||
while (1) {
|
while (1) {
|
||||||
rmff_last_error = RMFF_ERR_OK;
|
rmff_last_error = RMFF_ERR_OK;
|
||||||
@ -368,10 +402,10 @@ rmff_read_headers(rmff_file_t *file) {
|
|||||||
read_uint32_be_to(&prop->data_offset);
|
read_uint32_be_to(&prop->data_offset);
|
||||||
read_uint16_be_to(&prop->num_streams);
|
read_uint16_be_to(&prop->num_streams);
|
||||||
read_uint16_be_to(&prop->flags);
|
read_uint16_be_to(&prop->flags);
|
||||||
file->prop_header_found = 1;
|
prop_header_found = 1;
|
||||||
|
|
||||||
} else if (object_id == rmffFOURCC('C', 'O', 'N', 'T')) {
|
} else if (object_id == rmffFOURCC('C', 'O', 'N', 'T')) {
|
||||||
if (file->cont_header_found) {
|
if (file->cont_header_present) {
|
||||||
safefree(cont->title);
|
safefree(cont->title);
|
||||||
safefree(cont->author);
|
safefree(cont->author);
|
||||||
safefree(cont->copyright);
|
safefree(cont->copyright);
|
||||||
@ -399,7 +433,7 @@ rmff_read_headers(rmff_file_t *file) {
|
|||||||
cont->comment = (char *)safemalloc(size + 1);
|
cont->comment = (char *)safemalloc(size + 1);
|
||||||
io->read(fh, cont->comment, size);
|
io->read(fh, cont->comment, size);
|
||||||
}
|
}
|
||||||
file->cont_header_found = 1;
|
file->cont_header_present = 1;
|
||||||
|
|
||||||
} else if (object_id == rmffFOURCC('M', 'D', 'P', 'R')) {
|
} else if (object_id == rmffFOURCC('M', 'D', 'P', 'R')) {
|
||||||
memset(&track, 0, sizeof(rmff_track_t));
|
memset(&track, 0, sizeof(rmff_track_t));
|
||||||
@ -464,7 +498,7 @@ rmff_read_headers(rmff_file_t *file) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file->prop_header_found && (file->first_data_header_offset > 0)) {
|
if (prop_header_found && (file->first_data_header_offset > 0)) {
|
||||||
file->headers_read = 1;
|
file->headers_read = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -481,7 +515,7 @@ rmff_get_next_frame_size(rmff_file_t *file) {
|
|||||||
int64_t old_pos;
|
int64_t old_pos;
|
||||||
|
|
||||||
if ((file == NULL) || (!file->headers_read) || (file->io == NULL) ||
|
if ((file == NULL) || (!file->headers_read) || (file->io == NULL) ||
|
||||||
(file->handle == NULL))
|
(file->handle == NULL) || (file->open_mode != RMFF_OPEN_MODE_READING))
|
||||||
return set_error(RMFF_ERR_PARAMETERS, NULL, RMFF_ERR_PARAMETERS);
|
return set_error(RMFF_ERR_PARAMETERS, NULL, RMFF_ERR_PARAMETERS);
|
||||||
io = file->io;
|
io = file->io;
|
||||||
fh = file->handle;
|
fh = file->handle;
|
||||||
@ -514,7 +548,7 @@ rmff_read_next_frame(rmff_file_t *file,
|
|||||||
void *fh;
|
void *fh;
|
||||||
|
|
||||||
if ((file == NULL) || (!file->headers_read) || (file->io == NULL) ||
|
if ((file == NULL) || (!file->headers_read) || (file->io == NULL) ||
|
||||||
(file->handle == NULL))
|
(file->handle == NULL) || (file->open_mode != RMFF_OPEN_MODE_READING))
|
||||||
return (rmff_frame_t *)set_error(RMFF_ERR_PARAMETERS, NULL, 0);
|
return (rmff_frame_t *)set_error(RMFF_ERR_PARAMETERS, NULL, 0);
|
||||||
io = file->io;
|
io = file->io;
|
||||||
fh = file->handle;
|
fh = file->handle;
|
||||||
@ -562,3 +596,22 @@ rmff_release_frame(rmff_frame_t *frame) {
|
|||||||
safefree(frame->data);
|
safefree(frame->data);
|
||||||
safefree(frame);
|
safefree(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rmff_set_cont_header(rmff_file_t *file,
|
||||||
|
const char *title,
|
||||||
|
const char *author,
|
||||||
|
const char *copyright,
|
||||||
|
const char *comment) {
|
||||||
|
if (file == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
safefree(file->cont_header.title);
|
||||||
|
safefree(file->cont_header.author);
|
||||||
|
safefree(file->cont_header.copyright);
|
||||||
|
safefree(file->cont_header.comment);
|
||||||
|
file->cont_header.title = safestrdup(title);
|
||||||
|
file->cont_header.author = safestrdup(author);
|
||||||
|
file->cont_header.copyright = safestrdup(copyright);
|
||||||
|
file->cont_header.comment = safestrdup(comment);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user