mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-25 04:11:44 +00:00
Merged 1572:1575.
This commit is contained in:
parent
484b0c2fd9
commit
6d7ae72724
@ -24,6 +24,82 @@
|
|||||||
* \author Moritz Bunkus <moritz@bunkus.org>
|
* \author Moritz Bunkus <moritz@bunkus.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** \mainpage
|
||||||
|
*
|
||||||
|
* \section Introduction
|
||||||
|
*
|
||||||
|
* \a librmff is short for 'RealMedia file format access library'. It aims
|
||||||
|
* at providing the programmer an easy way to read and write RealMedia
|
||||||
|
* files. It does not contain any codecs for audio/video handling.
|
||||||
|
*
|
||||||
|
* \section License
|
||||||
|
*
|
||||||
|
* The library was written by Moritz Bunkus <moritz@bunkus.org>. It is
|
||||||
|
* licensed under the terms of the GNU Lesser General Public License (GNU
|
||||||
|
* LGPL) which can be found in the file COPYING.
|
||||||
|
*
|
||||||
|
* \section Usage
|
||||||
|
*
|
||||||
|
* Here are very short samples of how to use the library.
|
||||||
|
*
|
||||||
|
* \subsection reading_existing Reading an existing file
|
||||||
|
*
|
||||||
|
* Reading an existing file requires four steps: Opening the file, reading
|
||||||
|
* the headers, reading all the frames and closing the file.
|
||||||
|
*
|
||||||
|
* \code
|
||||||
|
rmff_file_t *file;
|
||||||
|
rmff_frame_t *frame;
|
||||||
|
|
||||||
|
file = rmff_open_file("sample_file.rm", RMFF_OPEN_MODE_READING);
|
||||||
|
if (file == NULL) {
|
||||||
|
// Output some general information about the tracks in the file.
|
||||||
|
// Now read all the frames.
|
||||||
|
while ((frame = rmff_read_next_frame(file, NULL)) != NULL) {
|
||||||
|
// Do something with the frame and release it afterwards.
|
||||||
|
rmff_release_frame(frame);
|
||||||
|
}
|
||||||
|
rmff_close_file(file);
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
*
|
||||||
|
* \section memory_handling Memory handling
|
||||||
|
*
|
||||||
|
* Generally \a librmff allocates and frees memory itself. You should
|
||||||
|
* \b never mess with pointers inside the structures directly but use
|
||||||
|
* the provided functions for manipulating it. There's one exception to
|
||||||
|
* this rule: the frame handling.
|
||||||
|
*
|
||||||
|
* The functions rmff_read_next_frame(rmff_file_t*,void*),
|
||||||
|
* rmff_release_frame(rmff_frame_t*) and
|
||||||
|
* rmff_allocate_frame(uint32_t,void*) allow the application to provide its
|
||||||
|
* own buffers for storing the frame contents. \a librmff will not copy
|
||||||
|
* this memory further. It will read directly into the buffer or write directly
|
||||||
|
* from the buffer into the file.
|
||||||
|
*
|
||||||
|
* Example: \code
|
||||||
|
rmff_frame_t *frame;
|
||||||
|
unsigned char *buffer,
|
||||||
|
int size;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
// Get the next frame's size.
|
||||||
|
size = rmff_get_next_frame_size(file);
|
||||||
|
// Have we reached the end of the file?
|
||||||
|
if (size == -1)
|
||||||
|
break;
|
||||||
|
// Allocate enough space for this frame and let librmff read directly
|
||||||
|
// into it.
|
||||||
|
buffer = (unsigned char *)malloc(size);
|
||||||
|
frame = rmff_read_next_frame(file, buffer);
|
||||||
|
// Now do something with the buffer. Afterwards release the frame.
|
||||||
|
rmff_release_frame(frame);
|
||||||
|
// The buffer is still allocated. So free it now.
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef __RMFF_H
|
#ifndef __RMFF_H
|
||||||
#define __RMFF_H
|
#define __RMFF_H
|
||||||
|
|
||||||
@ -36,9 +112,14 @@ extern "C" {
|
|||||||
|
|
||||||
#include "mb_file_io.h"
|
#include "mb_file_io.h"
|
||||||
|
|
||||||
/** \brief Contains the PROP file header.
|
/** \brief The global PROP file header.
|
||||||
|
*
|
||||||
* This header is mandatory for a RealMedia file. It contains statistical
|
* This header is mandatory for a RealMedia file. It contains statistical
|
||||||
* and global data. Each member is in big endian.
|
* and global data. The values are stored in big endian byte order.
|
||||||
|
* The application should use the functions
|
||||||
|
* rmff_get_uint16_be(const void*), rmff_get_uint32_be(const void*),
|
||||||
|
* rmff_put_uint16_be(void*,uint16_t) and
|
||||||
|
* rmff_put_uint32_be(void*,uint32_t) for accessing the members.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t max_bit_rate;
|
uint32_t max_bit_rate;
|
||||||
@ -55,9 +136,10 @@ typedef struct {
|
|||||||
} rmff_prop_t;
|
} rmff_prop_t;
|
||||||
|
|
||||||
/** \brief Comments about the file in question.
|
/** \brief Comments about the file in question.
|
||||||
|
*
|
||||||
* This structure contains the parsed values of the CONT header. These
|
* This structure contains the parsed values of the CONT header. These
|
||||||
* strings must not be modified by the application. The function
|
* strings must not be modified by the application. The function
|
||||||
* rmff_set_cont_header(const_char*,const_char*,const_char*,const_char*)
|
* rmff_set_cont_header(rmff_file_t*,const char*,const char*,const char*,const char*)
|
||||||
* must be used instead.
|
* must be used instead.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -67,18 +149,59 @@ typedef struct {
|
|||||||
char *comment;
|
char *comment;
|
||||||
} rmff_cont_t;
|
} rmff_cont_t;
|
||||||
|
|
||||||
|
/** \brief The MDPR track headers.
|
||||||
|
*
|
||||||
|
* Each track in a RealMedia file contains the MDPR header. The values
|
||||||
|
* are stored in big endian byte order.
|
||||||
|
* The application should use the functions
|
||||||
|
* rmff_get_uint16_be(const void*), rmff_get_uint32_be(const void*),
|
||||||
|
* rmff_put_uint16_be(void*,uint16_t) and
|
||||||
|
* rmff_put_uint32_be(void*,uint32_t) for accessing the members.
|
||||||
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
/** \brief The track number. It is unique regarding the file. */
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
|
/** \brief The maximum bitrate in bit/second.
|
||||||
|
*
|
||||||
|
* When creating a file this value will
|
||||||
|
* be updated automatically by the library. */
|
||||||
uint32_t max_bit_rate;
|
uint32_t max_bit_rate;
|
||||||
|
/** \brief The average bitrate in bit/second.
|
||||||
|
*
|
||||||
|
* When creating a file this value will
|
||||||
|
* be updated automatically by the library. */
|
||||||
uint32_t avg_bit_rate;
|
uint32_t avg_bit_rate;
|
||||||
|
/** \brief The maximum packet size in bytes.
|
||||||
|
*
|
||||||
|
* When creating a file this value will
|
||||||
|
* be updated automatically by the library. */
|
||||||
uint32_t max_packet_size;
|
uint32_t max_packet_size;
|
||||||
|
/** \brief The average packet size in bytes.
|
||||||
|
*
|
||||||
|
* When creating a file this value will
|
||||||
|
* be updated automatically by the library. */
|
||||||
uint32_t avg_packet_size;
|
uint32_t avg_packet_size;
|
||||||
uint32_t start_time;
|
uint32_t start_time;
|
||||||
uint32_t preroll;
|
uint32_t preroll;
|
||||||
uint32_t duration;
|
uint32_t duration;
|
||||||
|
/** \brief The track's name.
|
||||||
|
*
|
||||||
|
* Use the rmff_set_track_data(rmff_track_t*,const char*,const char*)
|
||||||
|
* function for setting it. */
|
||||||
char *name;
|
char *name;
|
||||||
|
/** \brief The track's MIME type.
|
||||||
|
*
|
||||||
|
* Use the rmff_set_track_data(rmff_track_t*,const char*,const char*)
|
||||||
|
* function for setting it. */
|
||||||
char *mime_type;
|
char *mime_type;
|
||||||
|
/** \brief The size of the track specific data in bytes. */
|
||||||
uint32_t type_specific_size;
|
uint32_t type_specific_size;
|
||||||
|
/** \brief Track type specific data.
|
||||||
|
*
|
||||||
|
* Use the
|
||||||
|
* rmff_set_track_specific_data(rmff_track_t*,const unsigned char*,uint32_t)
|
||||||
|
* function for setting it. It usually contains a ::real_video_props_t or
|
||||||
|
* ::real_audio_v4_props_t structure. */
|
||||||
unsigned char *type_specific_data;
|
unsigned char *type_specific_data;
|
||||||
} rmff_mdpr_t;
|
} rmff_mdpr_t;
|
||||||
|
|
||||||
@ -162,7 +285,7 @@ typedef struct rmff_frame_t {
|
|||||||
/** \brief The track contains video data. */
|
/** \brief The track contains video data. */
|
||||||
#define RMFF_TRACK_TYPE_VIDEO 2
|
#define RMFF_TRACK_TYPE_VIDEO 2
|
||||||
|
|
||||||
struct rmff_file_t ;
|
struct rmff_file_t;
|
||||||
|
|
||||||
typedef struct rmff_track_t {
|
typedef struct rmff_track_t {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
@ -210,15 +333,18 @@ typedef struct rmff_file_t {
|
|||||||
/** \brief An error has occured for which \c errno should be consulted. */
|
/** \brief An error has occured for which \c errno should be consulted. */
|
||||||
#define RMFF_ERR_CHECK_ERRNO -6
|
#define RMFF_ERR_CHECK_ERRNO -6
|
||||||
|
|
||||||
#define rmffFOURCC(a, b, c, d) (uint32_t)((((unsigned char)a) << 24) + \
|
/** \brief Convert the four bytes into a 'FOURCC' uint32. */
|
||||||
(((unsigned char)b) << 16) + \
|
#define rmffFOURCC(a, b, c, d) \
|
||||||
(((unsigned char)c) << 8) + \
|
(uint32_t)((((unsigned char)a) << 24) + \
|
||||||
((unsigned char)d))
|
(((unsigned char)b) << 16) + \
|
||||||
|
(((unsigned char)c) << 8) + \
|
||||||
|
((unsigned char)d))
|
||||||
|
|
||||||
#define RMFF_OPEN_MODE_READING 0
|
#define RMFF_OPEN_MODE_READING 0
|
||||||
#define RMFF_OPEN_MODE_WRITING 1
|
#define RMFF_OPEN_MODE_WRITING 1
|
||||||
|
|
||||||
/** \brief Opens a RealMedia file for reading or writing.
|
/** \brief Opens a RealMedia file for reading or writing.
|
||||||
|
*
|
||||||
* Can be used to open an existing file for reading or for creating a new
|
* Can be used to open an existing file for reading or for creating a new
|
||||||
* file. The file headers will neither be read nor written automatically.
|
* file. The file headers will neither be read nor written automatically.
|
||||||
* This function uses the standard file I/O functions provided by the
|
* This function uses the standard file I/O functions provided by the
|
||||||
@ -226,16 +352,17 @@ typedef struct rmff_file_t {
|
|||||||
*
|
*
|
||||||
* \param path the name of the file that should be opened
|
* \param path the name of the file that should be opened
|
||||||
* \param mode either ::RMFF_OPEN_MODE_READING or ::RMFF_OPEN_MODE_WRITING
|
* \param mode either ::RMFF_OPEN_MODE_READING or ::RMFF_OPEN_MODE_WRITING
|
||||||
* \returns a pointer to \c rmff_file_t structure or \c NULL if an error
|
* \returns a pointer to ::rmff_file_t structure or \c NULL if an error
|
||||||
* occured. In the latter case ::rmff_last_error will be set.
|
* occured. In the latter case ::rmff_last_error will be set.
|
||||||
* \see rmff_open_file_with_io
|
* \see rmff_open_file_with_io
|
||||||
*/
|
*/
|
||||||
rmff_file_t *rmff_open_file(const char *path, int mode);
|
rmff_file_t *rmff_open_file(const char *path, int mode);
|
||||||
|
|
||||||
/** \brief Opens a RealMedia file for reading or writing.
|
/** \brief Opens a RealMedia file for reading or writing.
|
||||||
|
*
|
||||||
* Can be used to open an existing file for reading or for creating a new
|
* Can be used to open an existing file for reading or for creating a new
|
||||||
* file. The file headers will neither be read nor written automatically.
|
* file. The file headers will neither be read nor written automatically.
|
||||||
* This function uses I/O functions provided by the \c io parameter.
|
* This function uses I/O functions provided by the \a io parameter.
|
||||||
*
|
*
|
||||||
* \param path the name of the file that should be opened
|
* \param path the name of the file that should be opened
|
||||||
* \param mode either ::RMFF_OPEN_MODE_READING or ::RMFF_OPEN_MODE_WRITING
|
* \param mode either ::RMFF_OPEN_MODE_READING or ::RMFF_OPEN_MODE_WRITING
|
||||||
@ -248,8 +375,9 @@ rmff_file_t *rmff_open_file_with_io(const char *path, int mode,
|
|||||||
mb_file_io_t *io);
|
mb_file_io_t *io);
|
||||||
|
|
||||||
/** \brief Close the file and release all resources.
|
/** \brief Close the file and release all resources.
|
||||||
|
*
|
||||||
* Closes the file and releases all resources associated with it, including
|
* Closes the file and releases all resources associated with it, including
|
||||||
* the \c file structure. If the file was open for writing then
|
* the ::rmff_file_t structure. If the file was open for writing then
|
||||||
* rmff_write_headers() should be called prior to closing the file as
|
* rmff_write_headers() should be called prior to closing the file as
|
||||||
* \c rmff_close_file does not fix the headers itself.
|
* \c rmff_close_file does not fix the headers itself.
|
||||||
*
|
*
|
||||||
@ -258,6 +386,7 @@ rmff_file_t *rmff_open_file_with_io(const char *path, int mode,
|
|||||||
void rmff_close_file(rmff_file_t *file);
|
void rmff_close_file(rmff_file_t *file);
|
||||||
|
|
||||||
/** \brief Reads the file and track headers.
|
/** \brief Reads the file and track headers.
|
||||||
|
*
|
||||||
* This function should be called after directly after opening it for reading.
|
* This function should be called after directly after opening it for reading.
|
||||||
* It will try to read the file and track headers and position the file pointer
|
* It will try to read the file and track headers and position the file pointer
|
||||||
* right before the first data packet.
|
* right before the first data packet.
|
||||||
@ -277,30 +406,47 @@ int rmff_read_headers(rmff_file_t *file);
|
|||||||
int rmff_get_next_frame_size(rmff_file_t *file);
|
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.
|
||||||
* If the application provides the buffer it must be large enough.
|
* If the application provides the buffer it must be large enough.
|
||||||
* The function rmff_get_next_frame_size() can be used in this case.
|
* The function rmff_get_next_frame_size(rmff_file_t*) can be used in this
|
||||||
|
* case.
|
||||||
* \returns a pointer to a ::rmff_frame_t structure containing the frame
|
* \returns a pointer to a ::rmff_frame_t structure containing the frame
|
||||||
* and its metadata on success or \c NULL if the call failed. This frame
|
* and its metadata on success or \c NULL if the call failed. This frame
|
||||||
* must be freed with rmff_release_frame(rmff_frame_t*).
|
* must be freed with rmff_release_frame(rmff_frame_t*).
|
||||||
*/
|
*/
|
||||||
rmff_frame_t *rmff_read_next_frame(rmff_file_t *file, void *buffer);
|
rmff_frame_t *rmff_read_next_frame(rmff_file_t *file, void *buffer);
|
||||||
|
|
||||||
|
/** \brief Allocates a frame and possibly a buffer for its contents.
|
||||||
|
*
|
||||||
|
* \param size The size of this frame.
|
||||||
|
* \param buffer A buffer that holds the frame. This parameter may be
|
||||||
|
* \c NULL in which case the buffer will be allocated by the library.
|
||||||
|
* If the application provides the buffer it must be large enough.
|
||||||
|
* \returns a pointer to an empty ::rmff_frame_t structure which can be filled
|
||||||
|
* with the frame contents and its metadata. This frame
|
||||||
|
* must be freed with rmff_release_frame(rmff_frame_t*).
|
||||||
|
*/
|
||||||
|
rmff_frame_t *rmff_allocate_frame(uint32_t size, 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.
|
/** \brief Sets the contents of the \link ::rmff_cont_t CONT file header
|
||||||
|
* \endlink.
|
||||||
|
*
|
||||||
* Frees the old contents if any and allocates copies of the given
|
* Frees the old contents if any and allocates copies of the given
|
||||||
* strings. If the CONT header should be written to the file
|
* strings. If the CONT header should be written to the file
|
||||||
* in rmff_write_headers(rmff_file_t*) then the \c cont_header_found
|
* in rmff_write_headers(rmff_file_t*) then the \a cont_header_present
|
||||||
* member must be set to 1.
|
* member must be set to 1.
|
||||||
*
|
*
|
||||||
* \param file The file whose CONT header should be set.
|
* \param file The file whose CONT header should be set.
|
||||||
@ -313,9 +459,38 @@ void rmff_set_cont_header(rmff_file_t *file, const char *title,
|
|||||||
const char *author, const char *copyright,
|
const char *author, const char *copyright,
|
||||||
const char *comment);
|
const char *comment);
|
||||||
|
|
||||||
|
/** \brief Sets the strings in the \link ::rmff_mdpr_t MDPR track header
|
||||||
|
* \endlink structure.
|
||||||
|
*
|
||||||
|
* Frees the old contents and allocates copies of the given strings.
|
||||||
|
*
|
||||||
|
* \param track The track whose MDPR header should be set.
|
||||||
|
* \param name The track's name.
|
||||||
|
* \param mime_type The MIME type. A video track should have the MIME type
|
||||||
|
* \c video/x-pn-realvideo, and an audio track should have the MIMT type
|
||||||
|
* \c audio/x-pn-realaudio.
|
||||||
|
*/
|
||||||
|
void rmff_set_track_data(rmff_track_t *track, const char *name,
|
||||||
|
const char *mime_type);
|
||||||
|
|
||||||
|
/** \brief Sets the \a track_specific_data member of the \link ::rmff_mdpr_t
|
||||||
|
* MDPR header\endlink structure.
|
||||||
|
*
|
||||||
|
* The \a track_specific_data usually contains a
|
||||||
|
* ::real_video_props_t structure or a ::real_audio_props_t structure.
|
||||||
|
* The existing data, if any, will be freed, and a copy of the memory
|
||||||
|
* \a data points to will be made.
|
||||||
|
*
|
||||||
|
* \param track The track whose MDPR header should be set.
|
||||||
|
* \param data A pointer to the track specific data.
|
||||||
|
* \param size The track specific data's size in bytes.
|
||||||
|
*/
|
||||||
|
void rmff_set_track_specific_data(rmff_track_t *track,
|
||||||
|
const unsigned char *data, uint32_t size);
|
||||||
|
|
||||||
/** \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
|
||||||
* succeeded it usually does not reset \c rmff_last_error to \c RMFF_ERR_OK.
|
* succeeded it usually does not reset \a rmff_last_error to \c RMFF_ERR_OK.
|
||||||
* This variable can contain one of the \c RMFF_ERR_* constants.
|
* This variable can contain one of the \c RMFF_ERR_* constants.
|
||||||
*/
|
*/
|
||||||
extern int rmff_last_error;
|
extern int rmff_last_error;
|
||||||
@ -334,6 +509,42 @@ extern const char *rmff_last_error_msg;
|
|||||||
*/
|
*/
|
||||||
const char *rmff_get_error_str(int code);
|
const char *rmff_get_error_str(int code);
|
||||||
|
|
||||||
|
/** \brief Reads a 16bit uint from an address.
|
||||||
|
* The uint is converted from big endian byte order to the machine's byte
|
||||||
|
* order.
|
||||||
|
*
|
||||||
|
* \param buf The address to read from.
|
||||||
|
* \returns The 16bit uint converted to the machine's byte order.
|
||||||
|
*/
|
||||||
|
uint16_t rmff_get_uint16_be(const void *buf);
|
||||||
|
|
||||||
|
/** \brief Reads a 32bit uint from an address.
|
||||||
|
* The uint is converted from big endian byte order to the machine's byte
|
||||||
|
* order.
|
||||||
|
*
|
||||||
|
* \param buf The address to read from.
|
||||||
|
* \returns The 32bit uint converted to the machine's byte order.
|
||||||
|
*/
|
||||||
|
uint32_t rmff_get_uint32_be(const void *buf);
|
||||||
|
|
||||||
|
/** \brief Write a 16bit uint at an address.
|
||||||
|
* The value is converted from the machine's byte order to big endian byte
|
||||||
|
* order.
|
||||||
|
*
|
||||||
|
* \param buf The address to write to.
|
||||||
|
* \param value The value to write.
|
||||||
|
*/
|
||||||
|
void rmff_put_uint16_be(void *buf, uint16_t value);
|
||||||
|
|
||||||
|
/** \brief Write a 32bit uint at an address.
|
||||||
|
* The value is converted from the machine's byte order to big endian byte
|
||||||
|
* order.
|
||||||
|
*
|
||||||
|
* \param buf The address to write to.
|
||||||
|
* \param value The value to write.
|
||||||
|
*/
|
||||||
|
void rmff_put_uint32_be(void *buf, uint32_t value);
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
107
librmff/rmff.c
107
librmff/rmff.c
@ -60,8 +60,8 @@ set_error(int error_number,
|
|||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t
|
uint16_t
|
||||||
get_uint16_be(const void *buf) {
|
rmff_get_uint16_be(const void *buf) {
|
||||||
uint16_t ret;
|
uint16_t ret;
|
||||||
unsigned char *tmp;
|
unsigned char *tmp;
|
||||||
|
|
||||||
@ -73,8 +73,8 @@ get_uint16_be(const void *buf) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t
|
uint32_t
|
||||||
get_uint32_be(const void *buf) {
|
rmff_get_uint32_be(const void *buf) {
|
||||||
uint32_t ret;
|
uint32_t ret;
|
||||||
unsigned char *tmp;
|
unsigned char *tmp;
|
||||||
|
|
||||||
@ -88,8 +88,8 @@ get_uint32_be(const void *buf) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
put_uint16_be(void *buf,
|
rmff_put_uin16_be(void *buf,
|
||||||
uint16_t value) {
|
uint16_t value) {
|
||||||
unsigned char *tmp;
|
unsigned char *tmp;
|
||||||
|
|
||||||
@ -99,8 +99,8 @@ put_uint16_be(void *buf,
|
|||||||
tmp[0] = (value >>= 8) & 0xff;
|
tmp[0] = (value >>= 8) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
put_uint32_be(void *buf,
|
rmff_put_uin32_be(void *buf,
|
||||||
uint32_t value) {
|
uint32_t value) {
|
||||||
unsigned char *tmp;
|
unsigned char *tmp;
|
||||||
|
|
||||||
@ -115,9 +115,9 @@ put_uint32_be(void *buf,
|
|||||||
#define read_uint8() file_read_uint8(io, fh)
|
#define read_uint8() file_read_uint8(io, fh)
|
||||||
#define read_uint16_be() file_read_uint16_be(io, fh)
|
#define read_uint16_be() file_read_uint16_be(io, fh)
|
||||||
#define read_uint32_be() file_read_uint32_be(io, fh)
|
#define read_uint32_be() file_read_uint32_be(io, fh)
|
||||||
#define read_uint16_be_to(addr) put_uint16_be(addr, read_uint16_be())
|
#define read_uint16_be_to(addr) rmff_put_uin16_be(addr, read_uint16_be())
|
||||||
#define read_uint32_be_to(addr) put_uint32_be(addr, read_uint32_be())
|
#define read_uint32_be_to(addr) rmff_put_uin32_be(addr, read_uint32_be())
|
||||||
#define get_fourcc(b) get_uint32_be(b)
|
#define get_fourcc(b) rmff_get_uint32_be(b)
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
file_read_uint8(mb_file_io_t *io,
|
file_read_uint8(mb_file_io_t *io,
|
||||||
@ -134,7 +134,7 @@ file_read_uint16_be(mb_file_io_t *io,
|
|||||||
unsigned char tmp[2];
|
unsigned char tmp[2];
|
||||||
|
|
||||||
io->read(fh, tmp, 2);
|
io->read(fh, tmp, 2);
|
||||||
return get_uint16_be(tmp);
|
return rmff_get_uint16_be(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
@ -143,7 +143,7 @@ file_read_uint32_be(mb_file_io_t *io,
|
|||||||
unsigned char tmp[4];
|
unsigned char tmp[4];
|
||||||
|
|
||||||
io->read(fh, tmp, 4);
|
io->read(fh, tmp, 4);
|
||||||
return get_uint32_be(tmp);
|
return rmff_get_uint32_be(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -183,24 +183,24 @@ _safestrdup(const char *s,
|
|||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static void * */
|
static void *
|
||||||
/* _safememdup(const void *s, */
|
_safememdup(const void *s,
|
||||||
/* size_t size, */
|
size_t size,
|
||||||
/* const char *file, */
|
const char *file,
|
||||||
/* int line) { */
|
int line) {
|
||||||
/* void *copy; */
|
void *copy;
|
||||||
|
|
||||||
/* if (s == NULL) */
|
if (s == NULL)
|
||||||
/* return NULL; */
|
return NULL;
|
||||||
|
|
||||||
/* copy = malloc(size); */
|
copy = malloc(size);
|
||||||
/* if (copy == NULL) */
|
if (copy == NULL)
|
||||||
/* die("safememdup() called from file %s, line %d: malloc() " */
|
die("safememdup() called from file %s, line %d: malloc() "
|
||||||
/* "returned NULL for a size of %d bytes.", file, line, size); */
|
"returned NULL for a size of %d bytes.", file, line, size);
|
||||||
/* memcpy(copy, s, size); */
|
memcpy(copy, s, size);
|
||||||
|
|
||||||
/* return copy; */
|
return copy;
|
||||||
/* } */
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
_safemalloc(size_t size,
|
_safemalloc(size_t size,
|
||||||
@ -440,7 +440,7 @@ rmff_read_headers(rmff_file_t *file) {
|
|||||||
track.file = (struct rmff_file_t *)file;
|
track.file = (struct rmff_file_t *)file;
|
||||||
mdpr = &track.mdpr_header;
|
mdpr = &track.mdpr_header;
|
||||||
read_uint16_be_to(&mdpr->id);
|
read_uint16_be_to(&mdpr->id);
|
||||||
track.id = get_uint16_be(&mdpr->id);
|
track.id = rmff_get_uint16_be(&mdpr->id);
|
||||||
read_uint32_be_to(&mdpr->max_bit_rate);
|
read_uint32_be_to(&mdpr->max_bit_rate);
|
||||||
read_uint32_be_to(&mdpr->avg_bit_rate);
|
read_uint32_be_to(&mdpr->avg_bit_rate);
|
||||||
read_uint32_be_to(&mdpr->max_packet_size);
|
read_uint32_be_to(&mdpr->max_packet_size);
|
||||||
@ -474,7 +474,7 @@ rmff_read_headers(rmff_file_t *file) {
|
|||||||
(get_fourcc(&ra4p->fourcc1) ==
|
(get_fourcc(&ra4p->fourcc1) ==
|
||||||
rmffFOURCC('.', 'r', 'a', 0xfd))) {
|
rmffFOURCC('.', 'r', 'a', 0xfd))) {
|
||||||
track.type = RMFF_TRACK_TYPE_AUDIO;
|
track.type = RMFF_TRACK_TYPE_AUDIO;
|
||||||
if ((get_uint16_be(&ra4p->version1) == 5) &&
|
if ((rmff_get_uint16_be(&ra4p->version1) == 5) &&
|
||||||
(size < sizeof(real_audio_v5_props_t)))
|
(size < sizeof(real_audio_v5_props_t)))
|
||||||
return set_error(RMFF_ERR_DATA, "RealAudio v5 data indicated but "
|
return set_error(RMFF_ERR_DATA, "RealAudio v5 data indicated but "
|
||||||
"data too small", RMFF_ERR_DATA);
|
"data too small", RMFF_ERR_DATA);
|
||||||
@ -588,6 +588,24 @@ rmff_read_next_frame(rmff_file_t *file,
|
|||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rmff_frame_t *
|
||||||
|
rmff_allocate_frame(uint32_t size,
|
||||||
|
void *buffer) {
|
||||||
|
rmff_frame_t *frame;
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
return (rmff_frame_t *)set_error(RMFF_ERR_PARAMETERS, NULL, 0);
|
||||||
|
frame = (rmff_frame_t *)safecalloc(sizeof(rmff_frame_t));
|
||||||
|
if (buffer == NULL) {
|
||||||
|
buffer = safemalloc(size);
|
||||||
|
frame->allocated_by_rmff = 1;
|
||||||
|
}
|
||||||
|
frame->size = size;
|
||||||
|
frame->data = (unsigned char *)buffer;
|
||||||
|
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rmff_release_frame(rmff_frame_t *frame) {
|
rmff_release_frame(rmff_frame_t *frame) {
|
||||||
if (frame == NULL)
|
if (frame == NULL)
|
||||||
@ -615,3 +633,32 @@ rmff_set_cont_header(rmff_file_t *file,
|
|||||||
file->cont_header.copyright = safestrdup(copyright);
|
file->cont_header.copyright = safestrdup(copyright);
|
||||||
file->cont_header.comment = safestrdup(comment);
|
file->cont_header.comment = safestrdup(comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rmff_set_track_data(rmff_track_t *track,
|
||||||
|
const char *name,
|
||||||
|
const char *mime_type) {
|
||||||
|
if (track == NULL)
|
||||||
|
return;
|
||||||
|
if (name != track->mdpr_header.name) {
|
||||||
|
safefree(track->mdpr_header.name);
|
||||||
|
track->mdpr_header.name = safestrdup(name);
|
||||||
|
}
|
||||||
|
if (mime_type != track->mdpr_header.mime_type) {
|
||||||
|
safefree(track->mdpr_header.mime_type);
|
||||||
|
track->mdpr_header.mime_type = safestrdup(mime_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rmff_set_track_specific_data(rmff_track_t *track,
|
||||||
|
const unsigned char *data,
|
||||||
|
uint32_t size) {
|
||||||
|
if (track == NULL)
|
||||||
|
return;
|
||||||
|
if (data != track->mdpr_header.type_specific_data) {
|
||||||
|
safefree(track->mdpr_header.type_specific_data);
|
||||||
|
track->mdpr_header.type_specific_data =
|
||||||
|
(unsigned char *)safememdup(data, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user