diff options
Diffstat (limited to 'src/demuxers/demux_qt.c')
-rw-r--r-- | src/demuxers/demux_qt.c | 511 |
1 files changed, 296 insertions, 215 deletions
diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c index 0624dc673..dffcfac55 100644 --- a/src/demuxers/demux_qt.c +++ b/src/demuxers/demux_qt.c @@ -110,6 +110,8 @@ typedef unsigned int qt_atom; #define UDTA_ATOM QT_ATOM('u', 'd', 't', 'a') #define META_ATOM QT_ATOM('m', 'e', 't', 'a') +#define HDLR_ATOM QT_ATOM('h', 'd', 'l', 'r') +#define ILST_ATOM QT_ATOM('i', 'l', 's', 't') #define NAM_ATOM QT_ATOM(0xA9, 'n', 'a', 'm') #define CPY_ATOM QT_ATOM(0xA9, 'c', 'p', 'y') #define DES_ATOM QT_ATOM(0xA9, 'd', 'e', 's') @@ -121,6 +123,7 @@ typedef unsigned int qt_atom; #define WRT_ATOM QT_ATOM(0xA9, 'w', 'r', 't') #define DAY_ATOM QT_ATOM(0xA9, 'd', 'a', 'y') +#define RMRA_ATOM QT_ATOM('r', 'm', 'r', 'a') #define RMDA_ATOM QT_ATOM('r', 'm', 'd', 'a') #define RDRF_ATOM QT_ATOM('r', 'd', 'r', 'f') #define RMDR_ATOM QT_ATOM('r', 'm', 'd', 'r') @@ -135,8 +138,10 @@ typedef unsigned int qt_atom; #define MAX_PTS_DIFF 100000 -/* network bandwidth, cribbed from src/input/input_mms.c */ -const int64_t bandwidths[]={14400,19200,28800,33600,34430,57600, +/** + * @brief Network bandwidth, cribbed from src/input/input_mms.c + */ +static const int64_t bandwidths[]={14400,19200,28800,33600,34430,57600, 115200,262200,393216,524300,1544000,10485800}; /* these are things that can go wrong */ @@ -403,6 +408,10 @@ typedef struct { * demuxer is sending off to the audio decoder */ #define DEBUG_AUDIO_DEMUX 0 +/* define DEBUG_META_LOAD as 1 to see details about the metadata chunks the + * demuxer is reading from the file */ +#define DEBUG_META_LOAD 0 + /* Define DEBUG_DUMP_MOOV as 1 to dump the raw moov atom to disk. This is * particularly useful in debugging a file with a compressed moov (cmov) * atom. The atom will be dumped to the filename specified as @@ -410,10 +419,6 @@ typedef struct { #define DEBUG_DUMP_MOOV 0 #define RAW_MOOV_FILENAME "moovatom.raw" -#ifndef __GNUC__ -#define __attribute__(x) -#endif - #if DEBUG_ATOM_LOAD #define debug_atom_load printf #else @@ -444,6 +449,12 @@ static inline void XINE_FORMAT_PRINTF(1, 2) debug_video_demux(const char *format static inline void XINE_FORMAT_PRINTF(1, 2) debug_audio_demux(const char *format, ...) {} #endif +#if DEBUG_META_LOAD +#define debug_meta_load printf +#else +static inline void XINE_FORMAT_PRINTF(1, 2) debug_meta_load(const char *format, ...) {} +#endif + static inline void dump_moov_atom(unsigned char *moov_atom, int moov_atom_size) { #if DEBUG_DUMP_MOOV @@ -500,8 +511,8 @@ static void find_moov_atom(input_plugin_t *input, off_t *moov_offset, ATOM_PREAMBLE_SIZE) break; - atom_size = BE_32(&atom_preamble[0]); - atom = BE_32(&atom_preamble[4]); + atom_size = _X_BE_32(&atom_preamble[0]); + atom = _X_BE_32(&atom_preamble[4]); /* Special case alert: 'free' atoms sometimes masquerade as 'moov' * atoms. If this is a free atom, check for 'cmov' or 'mvhd' immediately @@ -515,8 +526,8 @@ static void find_moov_atom(input_plugin_t *input, off_t *moov_offset, /* if there is a cmov, qualify this free atom as the 'moov' atom * if no actual 'moov' atom is found. */ - if ((BE_32(&atom_preamble[4]) == CMOV_ATOM) || - (BE_32(&atom_preamble[4]) == MVHD_ATOM)) { + if ((_X_BE_32(&atom_preamble[4]) == CMOV_ATOM) || + (_X_BE_32(&atom_preamble[4]) == MVHD_ATOM)) { /* pos = current pos minus 2 atom preambles */ free_moov_offset = input->get_current_pos(input) - ATOM_PREAMBLE_SIZE * 2; free_moov_size = atom_size; @@ -560,9 +571,9 @@ static void find_moov_atom(input_plugin_t *input, off_t *moov_offset, ATOM_PREAMBLE_SIZE) break; - atom_size = BE_32(&atom_preamble[0]); + atom_size = _X_BE_32(&atom_preamble[0]); atom_size <<= 32; - atom_size |= BE_32(&atom_preamble[4]); + atom_size |= _X_BE_32(&atom_preamble[4]); atom_size -= ATOM_PREAMBLE_SIZE * 2; } else atom_size -= ATOM_PREAMBLE_SIZE; @@ -687,20 +698,20 @@ static int is_qt_file(input_plugin_t *qt_file) { if ((qt_file->get_capabilities(qt_file) & INPUT_CAP_SEEKABLE) == 0) { memset (&preview, 0, MAX_PREVIEW_SIZE); len = qt_file->get_optional_data(qt_file, preview, INPUT_OPTIONAL_DATA_PREVIEW); - if (BE_32(&preview[4]) == MOOV_ATOM) + if (_X_BE_32(&preview[4]) == MOOV_ATOM) return 1; else { - if (BE_32(&preview[4]) == FTYP_ATOM) { + if (_X_BE_32(&preview[4]) == FTYP_ATOM) { /* show some lenience if the first atom is 'ftyp'; the second atom * could be 'moov' */ - moov_atom_size = BE_32(&preview[0]); + moov_atom_size = _X_BE_32(&preview[0]); /* compute the size of the current atom plus the preamble of the * next atom; if the size is within the range on the preview buffer * then the next atom's preamble is in the preview buffer */ i = moov_atom_size + ATOM_PREAMBLE_SIZE; if (i >= MAX_PREVIEW_SIZE) return 0; - if (BE_32(&preview[i - 4]) == MOOV_ATOM) + if (_X_BE_32(&preview[i - 4]) == MOOV_ATOM) return 1; else return 0; @@ -728,52 +739,114 @@ static int is_qt_file(input_plugin_t *qt_file) { } } +static char *parse_data_atom(unsigned char *data_atom) { + const uint32_t data_atom_size = _X_BE_32(&data_atom[0]); + + static const int data_atom_max_version = 0; + const int data_atom_version = data_atom[8]; + + const size_t alloc_size = data_atom_size - 8 + 1; + char *alloc_str = NULL; + + if ( data_atom_version > data_atom_max_version ) { + debug_meta_load("demux_qt: version %d for data atom is higher than the highest supported version (%d)\n", + data_atom_version, data_atom_max_version); + return NULL; + } + + alloc_str = xine_xmalloc(alloc_size); + xine_fast_memcpy(alloc_str, &data_atom[16], alloc_size-1); + alloc_str[alloc_size-1] = '\0'; + + debug_meta_load("demux_qt: got a string of size %zd (%s)\n", alloc_size, alloc_str); + + return alloc_str; +} + /* parse out a meta data atom */ static void parse_meta_atom(qt_info *info, unsigned char *meta_atom) { - int i; - unsigned int meta_atom_size = BE_32(&meta_atom[0]); - qt_atom current_atom; - int string_size; - - for (i = 0; i < meta_atom_size - 4; i++) { - current_atom = BE_32(&meta_atom[i]); - - if (current_atom == ART_ATOM) { - string_size = BE_32(&meta_atom[i + 4]) - 16 + 1; - info->artist = xine_xmalloc(string_size); - strncpy(info->artist, &meta_atom[i + 20], string_size - 1); - info->artist[string_size - 1] = 0; - } else if (current_atom == NAM_ATOM) { - string_size = BE_32(&meta_atom[i + 4]) - 16 + 1; - info->name = xine_xmalloc(string_size); - strncpy(info->name, &meta_atom[i + 20], string_size - 1); - info->name[string_size - 1] = 0; - } else if (current_atom == ALB_ATOM) { - string_size = BE_32(&meta_atom[i + 4]) - 16 + 1; - info->album = xine_xmalloc(string_size); - strncpy(info->album, &meta_atom[i + 20], string_size - 1); - info->album[string_size - 1] = 0; - } else if (current_atom == GEN_ATOM) { - string_size = BE_32(&meta_atom[i + 4]) - 16 + 1; - info->genre = xine_xmalloc(string_size); - strncpy(info->genre, &meta_atom[i + 20], string_size - 1); - info->genre[string_size - 1] = 0; - } else if (current_atom == TOO_ATOM) { - string_size = BE_32(&meta_atom[i + 4]) - 16 + 1; - info->comment = xine_xmalloc(string_size); - strncpy(info->comment, &meta_atom[i + 20], string_size - 1); - info->comment[string_size - 1] = 0; - } else if (current_atom == WRT_ATOM) { - string_size = BE_32(&meta_atom[i + 4]) - 16 + 1; - info->composer = xine_xmalloc(string_size); - strncpy(info->composer, &meta_atom[i + 20], string_size - 1); - info->composer[string_size - 1] = 0; - } else if (current_atom == DAY_ATOM) { - string_size = BE_32(&meta_atom[i + 4]) - 16 + 1; - info->year = xine_xmalloc(string_size); - strncpy(info->year, &meta_atom[i + 20], string_size - 1); - info->year[string_size - 1] = 0; + static const uint32_t meta_atom_preamble_size = 12; + + const uint32_t meta_atom_size = _X_BE_32(&meta_atom[0]); + + static const int meta_atom_max_version = 0; + const int meta_atom_version = meta_atom[8]; + /* const uint32_t flags = _X_BE_24(&meta_atom[9]); */ + + uint32_t i = meta_atom_preamble_size; + + if ( meta_atom_version > meta_atom_max_version ) { + debug_meta_load("demux_qt: version %d for meta atom is higher than the highest supported version (%d)\n", + meta_atom_version, meta_atom_max_version); + return; + } + + while ( i < meta_atom_size ) { + const uint8_t *const current_atom = &meta_atom[i]; + const qt_atom current_atom_code = _X_BE_32(¤t_atom[4]); + const uint32_t current_atom_size = _X_BE_32(¤t_atom[0]); + uint32_t handler_type = 0; + + switch (current_atom_code) { + case HDLR_ATOM: { + static const int hdlr_atom_max_version = 0; + const int hdlr_atom_version = current_atom[8]; + + /* const uint32_t hdlr_atom_flags = _X_BE_24(¤t_atom[9]); */ + + if ( hdlr_atom_version > hdlr_atom_max_version ) { + debug_meta_load("demux_qt: version %d for hdlr atom is higher than the highest supported version (%d)\n", + hdlr_atom_version, hdlr_atom_max_version); + return; + } + + handler_type = _X_BE_32(¤t_atom[12]); } + break; + + case ILST_ATOM: { + uint32_t j = i + 8; + while ( j < current_atom_size ) { + const uint8_t *const sub_atom = &meta_atom[j]; + const qt_atom sub_atom_code = _X_BE_32(&sub_atom[4]); + const uint32_t sub_atom_size = _X_BE_32(&sub_atom[0]); + + switch(sub_atom_code) { + case ART_ATOM: + info->artist = parse_data_atom(&sub_atom[8]); + break; + case NAM_ATOM: + info->name = parse_data_atom(&sub_atom[8]); + break; + case ALB_ATOM: + info->album = parse_data_atom(&sub_atom[8]); + break; + case GEN_ATOM: + info->genre = parse_data_atom(&sub_atom[8]); + break; + case CMT_ATOM: + info->comment = parse_data_atom(&sub_atom[8]); + break; + case WRT_ATOM: + info->composer = parse_data_atom(&sub_atom[8]); + break; + case DAY_ATOM: + info->year = parse_data_atom(&sub_atom[8]); + break; + default: + debug_meta_load("unknown atom %08x in ilst\n", sub_atom_code); + } + + j += sub_atom_size; + } + } + break; + + default: + debug_meta_load("unknown atom %08x in meta\n", current_atom_code); + } + + i += current_atom_size; } } @@ -781,10 +854,10 @@ static void parse_meta_atom(qt_info *info, unsigned char *meta_atom) { /* fetch interesting information from the movie header atom */ static void parse_mvhd_atom(qt_info *info, unsigned char *mvhd_atom) { - info->creation_time = BE_32(&mvhd_atom[0x0C]); - info->modification_time = BE_32(&mvhd_atom[0x10]); - info->timescale = BE_32(&mvhd_atom[0x14]); - info->duration = BE_32(&mvhd_atom[0x18]); + info->creation_time = _X_BE_32(&mvhd_atom[0x0C]); + info->modification_time = _X_BE_32(&mvhd_atom[0x10]); + info->timescale = _X_BE_32(&mvhd_atom[0x14]); + info->duration = _X_BE_32(&mvhd_atom[0x18]); debug_atom_load(" qt: timescale = %d, duration = %d (%d seconds)\n", info->timescale, info->duration, @@ -815,25 +888,11 @@ static qt_error parse_trak_atom (qt_trak *trak, unsigned char *trak_atom) { int i, j, k; - unsigned int trak_atom_size = BE_32(&trak_atom[0]); - qt_atom current_atom; - unsigned int current_atom_size; + const unsigned int trak_atom_size = _X_BE_32(&trak_atom[0]); unsigned int atom_pos; unsigned int properties_offset; - unsigned int current_stsd_atom_size; qt_error last_error = QT_OK; - /* for palette traversal */ - int color_depth; - int color_flag; - int color_start; - int color_count; - int color_end; - int color_index; - int color_dec; - int color_greyscale; - const unsigned char *color_table; - /* initialize trak structure */ trak->edit_list_count = 0; trak->edit_list_table = NULL; @@ -864,12 +923,13 @@ static qt_error parse_trak_atom (qt_trak *trak, /* search for media type atoms */ for (i = ATOM_PREAMBLE_SIZE; i < trak_atom_size - 4; i++) { - current_atom = BE_32(&trak_atom[i]); + const qt_atom current_atom = _X_BE_32(&trak_atom[i]); - if (current_atom == VMHD_ATOM) { + switch (current_atom) { + case VMHD_ATOM: trak->type = MEDIA_VIDEO; break; - } else if (current_atom == SMHD_ATOM) { + case SMHD_ATOM: trak->type = MEDIA_AUDIO; break; } @@ -881,20 +941,22 @@ static qt_error parse_trak_atom (qt_trak *trak, /* search for the useful atoms */ for (i = ATOM_PREAMBLE_SIZE; i < trak_atom_size - 4; i++) { - current_atom_size = BE_32(&trak_atom[i - 4]); - current_atom = BE_32(&trak_atom[i]); + const current_atom_size = _X_BE_32(&trak_atom[i - 4]); + const current_atom = _X_BE_32(&trak_atom[i]); - if (current_atom == TKHD_ATOM) { - trak->flags = BE_16(&trak_atom[i + 6]); - } else if (current_atom == ELST_ATOM) { + switch(current_atom) { + case TKHD_ATOM: + trak->flags = _X_BE_16(&trak_atom[i + 6]); + break; + case ELST_ATOM: /* there should only be one edit list table */ if (trak->edit_list_table) { last_error = QT_HEADER_TROUBLE; goto free_trak; } - trak->edit_list_count = BE_32(&trak_atom[i + 8]); + trak->edit_list_count = _X_BE_32(&trak_atom[i + 8]); debug_atom_load(" qt elst atom (edit list atom): %d entries\n", trak->edit_list_count); @@ -909,44 +971,56 @@ static qt_error parse_trak_atom (qt_trak *trak, /* load the edit list table */ for (j = 0; j < trak->edit_list_count; j++) { trak->edit_list_table[j].track_duration = - BE_32(&trak_atom[i + 12 + j * 12 + 0]); + _X_BE_32(&trak_atom[i + 12 + j * 12 + 0]); trak->edit_list_table[j].media_time = - BE_32(&trak_atom[i + 12 + j * 12 + 4]); + _X_BE_32(&trak_atom[i + 12 + j * 12 + 4]); debug_atom_load(" %d: track duration = %d, media time = %d\n", j, trak->edit_list_table[j].track_duration, trak->edit_list_table[j].media_time); } + break; - } else if (current_atom == MDHD_ATOM) { - int version; + case MDHD_ATOM: debug_atom_load ("demux_qt: mdhd atom\n"); - - version = trak_atom[i+4]; - if ( version > 1 ) continue; /* unsupported, undocumented */ + { + const int version = trak_atom[i+4]; + if ( version > 1 ) continue; /* unsupported, undocumented */ - trak->timescale = BE_32(&trak_atom[i + (version == 0 ? 0x10 : 0x18) ]); - } else if (current_atom == STSD_ATOM) { + trak->timescale = _X_BE_32(&trak_atom[i + (version == 0 ? 0x10 : 0x18) ]); + } + break; + case STSD_ATOM: debug_atom_load ("demux_qt: stsd atom\n"); #if DEBUG_ATOM_LOAD xine_hexdump (&trak_atom[i], current_atom_size); #endif /* allocate space for each of the properties unions */ - trak->stsd_atoms_count = BE_32(&trak_atom[i + 8]); - trak->stsd_atoms = xine_xmalloc(trak->stsd_atoms_count * sizeof(properties_t)); + trak->stsd_atoms_count = _X_BE_32(&trak_atom[i + 8]); + trak->stsd_atoms = xine_xcalloc(trak->stsd_atoms_count, sizeof(properties_t)); if (!trak->stsd_atoms) { last_error = QT_NO_MEMORY; goto free_trak; } - memset(trak->stsd_atoms, 0, trak->stsd_atoms_count * sizeof(properties_t)); atom_pos = i + 0x10; properties_offset = 0x0C; for (k = 0; k < trak->stsd_atoms_count; k++) { - current_stsd_atom_size = BE_32(&trak_atom[atom_pos - 4]); + const uint32_t current_stsd_atom_size = _X_BE_32(&trak_atom[atom_pos - 4]); + + /* for palette traversal */ + int color_depth; + int color_flag; + int color_start; + int color_count; + int color_end; + int color_index; + int color_dec; + int color_greyscale; + const unsigned char *color_table; if (trak->type == MEDIA_VIDEO) { @@ -969,15 +1043,15 @@ static qt_error parse_trak_atom (qt_trak *trak, trak->stsd_atoms[k].video.palette_count = 0; /* fetch video parameters */ - if( BE_16(&trak_atom[atom_pos + 0x1C]) && - BE_16(&trak_atom[atom_pos + 0x1E]) ) { + if( _X_BE_16(&trak_atom[atom_pos + 0x1C]) && + _X_BE_16(&trak_atom[atom_pos + 0x1E]) ) { trak->stsd_atoms[k].video.width = - BE_16(&trak_atom[atom_pos + 0x1C]); + _X_BE_16(&trak_atom[atom_pos + 0x1C]); trak->stsd_atoms[k].video.height = - BE_16(&trak_atom[atom_pos + 0x1E]); + _X_BE_16(&trak_atom[atom_pos + 0x1E]); } trak->stsd_atoms[k].video.codec_fourcc = - ME_32(&trak_atom[atom_pos + 0x00]); + _X_ME_32(&trak_atom[atom_pos + 0x00]); /* figure out the palette situation */ color_depth = trak_atom[atom_pos + 0x4F]; @@ -988,7 +1062,7 @@ static qt_error parse_trak_atom (qt_trak *trak, /* if the depth is 2, 4, or 8 bpp, file is palettized */ if ((color_depth == 2) || (color_depth == 4) || (color_depth == 8)) { - color_flag = BE_16(&trak_atom[atom_pos + 0x50]); + color_flag = _X_BE_16(&trak_atom[atom_pos + 0x50]); if (color_greyscale) { @@ -1040,15 +1114,15 @@ static qt_error parse_trak_atom (qt_trak *trak, } else { /* load the palette from the file */ - color_start = BE_32(&trak_atom[atom_pos + 0x52]); - color_count = BE_16(&trak_atom[atom_pos + 0x56]); - color_end = BE_16(&trak_atom[atom_pos + 0x58]); + color_start = _X_BE_32(&trak_atom[atom_pos + 0x52]); + color_count = _X_BE_16(&trak_atom[atom_pos + 0x56]); + color_end = _X_BE_16(&trak_atom[atom_pos + 0x58]); trak->stsd_atoms[k].video.palette_count = color_end + 1; for (j = color_start; j <= color_end; j++) { - color_index = BE_16(&trak_atom[atom_pos + 0x5A + j * 8]); + color_index = _X_BE_16(&trak_atom[atom_pos + 0x5A + j * 8]); if (color_count & 0x8000) color_index = j; if (color_index < @@ -1101,9 +1175,9 @@ static qt_error parse_trak_atom (qt_trak *trak, /* fetch audio parameters */ trak->stsd_atoms[k].audio.codec_fourcc = - ME_32(&trak_atom[atom_pos + 0x0]); + _X_ME_32(&trak_atom[atom_pos + 0x0]); trak->stsd_atoms[k].audio.sample_rate = - BE_16(&trak_atom[atom_pos + 0x1C]); + _X_BE_16(&trak_atom[atom_pos + 0x1C]); trak->stsd_atoms[k].audio.channels = trak_atom[atom_pos + 0x15]; trak->stsd_atoms[k].audio.bits = trak_atom[atom_pos + 0x17]; @@ -1175,18 +1249,18 @@ static qt_error parse_trak_atom (qt_trak *trak, (trak->stsd_atoms[k].audio.codec_fourcc != SOWT_FOURCC) && (trak->stsd_atoms[k].audio.codec_fourcc != RAW_FOURCC)) { - if (BE_32(&trak_atom[atom_pos + 0x20])) + if (_X_BE_32(&trak_atom[atom_pos + 0x20])) trak->stsd_atoms[k].audio.samples_per_packet = - BE_32(&trak_atom[atom_pos + 0x20]); - if (BE_32(&trak_atom[atom_pos + 0x24])) + _X_BE_32(&trak_atom[atom_pos + 0x20]); + if (_X_BE_32(&trak_atom[atom_pos + 0x24])) trak->stsd_atoms[k].audio.bytes_per_packet = - BE_32(&trak_atom[atom_pos + 0x24]); - if (BE_32(&trak_atom[atom_pos + 0x28])) + _X_BE_32(&trak_atom[atom_pos + 0x24]); + if (_X_BE_32(&trak_atom[atom_pos + 0x28])) trak->stsd_atoms[k].audio.bytes_per_frame = - BE_32(&trak_atom[atom_pos + 0x28]); - if (BE_32(&trak_atom[atom_pos + 0x2C])) + _X_BE_32(&trak_atom[atom_pos + 0x28]); + if (_X_BE_32(&trak_atom[atom_pos + 0x2C])) trak->stsd_atoms[k].audio.bytes_per_sample = - BE_32(&trak_atom[atom_pos + 0x2C]); + _X_BE_32(&trak_atom[atom_pos + 0x2C]); trak->stsd_atoms[k].audio.samples_per_frame = (trak->stsd_atoms[k].audio.bytes_per_frame / trak->stsd_atoms[k].audio.bytes_per_packet) * @@ -1194,7 +1268,7 @@ static qt_error parse_trak_atom (qt_trak *trak, } /* see if the trak deserves a promotion to VBR */ - if (BE_16(&trak_atom[atom_pos + 0x18]) == 0xFFFE) + if (_X_BE_16(&trak_atom[atom_pos + 0x18]) == 0xFFFE) trak->stsd_atoms[k].audio.vbr = 1; else trak->stsd_atoms[k].audio.vbr = 0; @@ -1224,10 +1298,10 @@ static qt_error parse_trak_atom (qt_trak *trak, /* check for a MS-style WAVE format header */ if ((current_atom_size >= 0x4C) && - (BE_32(&trak_atom[atom_pos + 0x34]) == WAVE_ATOM) && - (BE_32(&trak_atom[atom_pos + 0x3C]) == FRMA_ATOM) && - (ME_32(&trak_atom[atom_pos + 0x48]) == trak->stsd_atoms[k].audio.codec_fourcc)) { - int wave_size = BE_32(&trak_atom[atom_pos + 0x44]) - 8; + (_X_BE_32(&trak_atom[atom_pos + 0x34]) == WAVE_ATOM) && + (_X_BE_32(&trak_atom[atom_pos + 0x3C]) == FRMA_ATOM) && + (_X_ME_32(&trak_atom[atom_pos + 0x48]) == trak->stsd_atoms[k].audio.codec_fourcc)) { + const int wave_size = _X_BE_32(&trak_atom[atom_pos + 0x44]) - 8; if ((wave_size >= sizeof(xine_waveformatex)) && (current_atom_size >= (0x4C + wave_size))) { @@ -1277,15 +1351,15 @@ static qt_error parse_trak_atom (qt_trak *trak, atom_pos += current_stsd_atom_size; properties_offset += current_stsd_atom_size; } - - } else if (current_atom == ESDS_ATOM) { - - uint32_t len; + break; + + case ESDS_ATOM: debug_atom_load(" qt/mpeg-4 esds atom\n"); if ((trak->type == MEDIA_VIDEO) || (trak->type == MEDIA_AUDIO)) { + uint32_t len; j = i + 8; if( trak_atom[j++] == 0x03 ) { @@ -1308,25 +1382,25 @@ static qt_error parse_trak_atom (qt_trak *trak, } } } + break; - } else if (current_atom == AVCC_ATOM) { - + case AVCC_ATOM: debug_atom_load(" avcC atom\n"); trak->decoder_config_len = current_atom_size - 8; trak->decoder_config = realloc(trak->decoder_config, trak->decoder_config_len); memcpy(trak->decoder_config, &trak_atom[i + 4], trak->decoder_config_len); + break; - } else if (current_atom == STSZ_ATOM) { - + case STSZ_ATOM: /* there should only be one of these atoms */ if (trak->sample_size_table) { last_error = QT_HEADER_TROUBLE; goto free_trak; } - trak->sample_size = BE_32(&trak_atom[i + 8]); - trak->sample_size_count = BE_32(&trak_atom[i + 12]); + trak->sample_size = _X_BE_32(&trak_atom[i + 8]); + trak->sample_size_count = _X_BE_32(&trak_atom[i + 12]); debug_atom_load(" qt stsz atom (sample size atom): sample size = %d, %d entries\n", trak->sample_size, trak->sample_size_count); @@ -1342,7 +1416,7 @@ static qt_error parse_trak_atom (qt_trak *trak, /* load the sample size table */ for (j = 0; j < trak->sample_size_count; j++) { trak->sample_size_table[j] = - BE_32(&trak_atom[i + 16 + j * 4]); + _X_BE_32(&trak_atom[i + 16 + j * 4]); debug_atom_load(" sample size %d: %d\n", j, trak->sample_size_table[j]); } @@ -1350,16 +1424,16 @@ static qt_error parse_trak_atom (qt_trak *trak, /* set the pointer to non-NULL to indicate that the atom type has * already been seen for this trak atom */ trak->sample_size_table = (void *)-1; + break; - } else if (current_atom == STSS_ATOM) { - + case STSS_ATOM: /* there should only be one of these atoms */ if (trak->sync_sample_table) { last_error = QT_HEADER_TROUBLE; goto free_trak; } - trak->sync_sample_count = BE_32(&trak_atom[i + 8]); + trak->sync_sample_count = _X_BE_32(&trak_atom[i + 8]); debug_atom_load(" qt stss atom (sample sync atom): %d sync samples\n", trak->sync_sample_count); @@ -1374,21 +1448,21 @@ static qt_error parse_trak_atom (qt_trak *trak, /* load the sync sample table */ for (j = 0; j < trak->sync_sample_count; j++) { trak->sync_sample_table[j] = - BE_32(&trak_atom[i + 12 + j * 4]); + _X_BE_32(&trak_atom[i + 12 + j * 4]); debug_atom_load(" sync sample %d: sample %d (%d) is a keyframe\n", j, trak->sync_sample_table[j], trak->sync_sample_table[j] - 1); } + break; - } else if (current_atom == STCO_ATOM) { - + case STCO_ATOM: /* there should only be one of either stco or co64 */ if (trak->chunk_offset_table) { last_error = QT_HEADER_TROUBLE; goto free_trak; } - trak->chunk_offset_count = BE_32(&trak_atom[i + 8]); + trak->chunk_offset_count = _X_BE_32(&trak_atom[i + 8]); debug_atom_load(" qt stco atom (32-bit chunk offset atom): %d chunk offsets\n", trak->chunk_offset_count); @@ -1403,20 +1477,20 @@ static qt_error parse_trak_atom (qt_trak *trak, /* load the chunk offset table */ for (j = 0; j < trak->chunk_offset_count; j++) { trak->chunk_offset_table[j] = - BE_32(&trak_atom[i + 12 + j * 4]); + _X_BE_32(&trak_atom[i + 12 + j * 4]); debug_atom_load(" chunk %d @ 0x%"PRIX64"\n", j, trak->chunk_offset_table[j]); } + break; - } else if (current_atom == CO64_ATOM) { - + case CO64_ATOM: /* there should only be one of either stco or co64 */ if (trak->chunk_offset_table) { last_error = QT_HEADER_TROUBLE; goto free_trak; } - trak->chunk_offset_count = BE_32(&trak_atom[i + 8]); + trak->chunk_offset_count = _X_BE_32(&trak_atom[i + 8]); debug_atom_load(" qt co64 atom (64-bit chunk offset atom): %d chunk offsets\n", trak->chunk_offset_count); @@ -1431,23 +1505,23 @@ static qt_error parse_trak_atom (qt_trak *trak, /* load the 64-bit chunk offset table */ for (j = 0; j < trak->chunk_offset_count; j++) { trak->chunk_offset_table[j] = - BE_32(&trak_atom[i + 12 + j * 8 + 0]); + _X_BE_32(&trak_atom[i + 12 + j * 8 + 0]); trak->chunk_offset_table[j] <<= 32; trak->chunk_offset_table[j] |= - BE_32(&trak_atom[i + 12 + j * 8 + 4]); + _X_BE_32(&trak_atom[i + 12 + j * 8 + 4]); debug_atom_load(" chunk %d @ 0x%"PRIX64"\n", j, trak->chunk_offset_table[j]); } + break; - } else if (current_atom == STSC_ATOM) { - + case STSC_ATOM: /* there should only be one of these atoms */ if (trak->sample_to_chunk_table) { last_error = QT_HEADER_TROUBLE; goto free_trak; } - trak->sample_to_chunk_count = BE_32(&trak_atom[i + 8]); + trak->sample_to_chunk_count = _X_BE_32(&trak_atom[i + 8]); debug_atom_load(" qt stsc atom (sample-to-chunk atom): %d entries\n", trak->sample_to_chunk_count); @@ -1462,27 +1536,27 @@ static qt_error parse_trak_atom (qt_trak *trak, /* load the sample to chunk table */ for (j = 0; j < trak->sample_to_chunk_count; j++) { trak->sample_to_chunk_table[j].first_chunk = - BE_32(&trak_atom[i + 12 + j * 12 + 0]); + _X_BE_32(&trak_atom[i + 12 + j * 12 + 0]); trak->sample_to_chunk_table[j].samples_per_chunk = - BE_32(&trak_atom[i + 12 + j * 12 + 4]); + _X_BE_32(&trak_atom[i + 12 + j * 12 + 4]); trak->sample_to_chunk_table[j].media_id = - BE_32(&trak_atom[i + 12 + j * 12 + 8]); + _X_BE_32(&trak_atom[i + 12 + j * 12 + 8]); debug_atom_load(" %d: %d samples/chunk starting at chunk %d (%d) for media id %d\n", j, trak->sample_to_chunk_table[j].samples_per_chunk, trak->sample_to_chunk_table[j].first_chunk, trak->sample_to_chunk_table[j].first_chunk - 1, trak->sample_to_chunk_table[j].media_id); } + break; - } else if (current_atom == STTS_ATOM) { - + case STTS_ATOM: /* there should only be one of these atoms */ if (trak->time_to_sample_table) { last_error = QT_HEADER_TROUBLE; goto free_trak; } - trak->time_to_sample_count = BE_32(&trak_atom[i + 8]); + trak->time_to_sample_count = _X_BE_32(&trak_atom[i + 8]); debug_atom_load(" qt stts atom (time-to-sample atom): %d entries\n", trak->time_to_sample_count); @@ -1497,9 +1571,9 @@ static qt_error parse_trak_atom (qt_trak *trak, /* load the time to sample table */ for (j = 0; j < trak->time_to_sample_count; j++) { trak->time_to_sample_table[j].count = - BE_32(&trak_atom[i + 12 + j * 8 + 0]); + _X_BE_32(&trak_atom[i + 12 + j * 8 + 0]); trak->time_to_sample_table[j].duration = - BE_32(&trak_atom[i + 12 + j * 8 + 4]); + _X_BE_32(&trak_atom[i + 12 + j * 8 + 4]); debug_atom_load(" %d: count = %d, duration = %d\n", j, trak->time_to_sample_table[j].count, trak->time_to_sample_table[j].duration); @@ -1535,9 +1609,7 @@ static qt_error parse_reference_atom (reference_t *ref, char *base_mrl) { int i, j; - unsigned int ref_atom_size = BE_32(&ref_atom[0]); - qt_atom current_atom; - unsigned int current_atom_size; + const unsigned int ref_atom_size = _X_BE_32(&ref_atom[0]); /* initialize reference atom */ ref->url = NULL; @@ -1546,59 +1618,59 @@ static qt_error parse_reference_atom (reference_t *ref, /* traverse through the atom looking for the key atoms */ for (i = ATOM_PREAMBLE_SIZE; i < ref_atom_size - 4; i++) { + const uint32_t current_atom_size = _X_BE_32(&ref_atom[i - 4]); + const qt_atom current_atom = _X_BE_32(&ref_atom[i]); - current_atom_size = BE_32(&ref_atom[i - 4]); - current_atom = BE_32(&ref_atom[i]); - - if (current_atom == RDRF_ATOM) { + switch (current_atom) { + case RDRF_ATOM: /* if the URL starts with "http://", copy it */ if (strncmp(&ref_atom[i + 16], "http://", 7) == 0 || strncmp(&ref_atom[i + 16], "rtsp://", 7) == 0) { /* URL is spec'd to terminate with a NULL; don't trust it */ - ref->url = xine_xmalloc(BE_32(&ref_atom[i + 12]) + 1); - strncpy(ref->url, &ref_atom[i + 16], BE_32(&ref_atom[i + 12])); - ref->url[BE_32(&ref_atom[i + 12]) - 1] = '\0'; + ref->url = xine_xmalloc(_X_BE_32(&ref_atom[i + 12]) + 1); + strncpy(ref->url, &ref_atom[i + 16], _X_BE_32(&ref_atom[i + 12])); + ref->url[_X_BE_32(&ref_atom[i + 12]) - 1] = '\0'; } else { int string_size; if (base_mrl) - string_size = strlen(base_mrl) + BE_32(&ref_atom[i + 12]) + 1; + string_size = strlen(base_mrl) + _X_BE_32(&ref_atom[i + 12]) + 1; else - string_size = BE_32(&ref_atom[i + 12]) + 1; + string_size = _X_BE_32(&ref_atom[i + 12]) + 1; /* otherwise, append relative URL to base MRL */ ref->url = xine_xmalloc(string_size); if (base_mrl) strcpy(ref->url, base_mrl); - strncat(ref->url, &ref_atom[i + 16], BE_32(&ref_atom[i + 12])); + strncat(ref->url, &ref_atom[i + 16], _X_BE_32(&ref_atom[i + 12])); ref->url[string_size - 1] = '\0'; } debug_atom_load(" qt rdrf URL reference:\n %s\n", ref->url); + break; - } else if (current_atom == RMDR_ATOM) { - + case RMDR_ATOM: /* load the data rate */ - ref->data_rate = BE_32(&ref_atom[i + 8]); + ref->data_rate = _X_BE_32(&ref_atom[i + 8]); ref->data_rate *= 10; debug_atom_load(" qt rmdr data rate = %"PRId64"\n", ref->data_rate); + break; - } else if (current_atom == RMVC_ATOM) { - + case RMVC_ATOM: debug_atom_load(" qt rmvc atom\n"); /* search the rmvc atom for 'qtim'; 2 bytes will follow the qtim * chars so only search to 6 bytes to the end */ for (j = 4; j < current_atom_size - 6; j++) { - if (BE_32(&ref_atom[i + j]) == QTIM_ATOM) { + if (_X_BE_32(&ref_atom[i + j]) == QTIM_ATOM) { - ref->qtim_version = BE_16(&ref_atom[i + j + 4]); + ref->qtim_version = _X_BE_16(&ref_atom[i + j + 4]); debug_atom_load(" qtim version = %04X\n", ref->qtim_version); } } @@ -1916,31 +1988,32 @@ static qt_error build_frame_table(qt_trak *trak, static void parse_moov_atom(qt_info *info, unsigned char *moov_atom, int64_t bandwidth) { int i, j; - unsigned int moov_atom_size = BE_32(&moov_atom[0]); - qt_atom current_atom; + unsigned int moov_atom_size = _X_BE_32(&moov_atom[0]); int string_size, error; unsigned int max_video_frames = 0; unsigned int max_audio_frames = 0; /* make sure this is actually a moov atom (will also accept 'free' as * a special case) */ - if ((BE_32(&moov_atom[4]) != MOOV_ATOM) && - (BE_32(&moov_atom[4]) != FREE_ATOM)) { + if ((_X_BE_32(&moov_atom[4]) != MOOV_ATOM) && + (_X_BE_32(&moov_atom[4]) != FREE_ATOM)) { info->last_error = QT_NO_MOOV_ATOM; return; } /* prowl through the moov atom looking for very specific targets */ - for (i = ATOM_PREAMBLE_SIZE + 4; i < moov_atom_size - 4; i += BE_32(&moov_atom[i - 4])) { - current_atom = BE_32(&moov_atom[i]); + for (i = ATOM_PREAMBLE_SIZE + 4; i < moov_atom_size - 4; i += _X_BE_32(&moov_atom[i - 4])) { + const qt_atom current_atom = _X_BE_32(&moov_atom[i]); - if (current_atom == MVHD_ATOM) { + switch (current_atom) { + case MVHD_ATOM: parse_mvhd_atom(info, &moov_atom[i - 4]); if (info->last_error != QT_OK) return; - } else if (current_atom == TRAK_ATOM) { + break; + case TRAK_ATOM: /* create a new trak structure */ info->trak_count++; info->traks = (qt_trak *)realloc(info->traks, @@ -1952,43 +2025,50 @@ static void parse_moov_atom(qt_info *info, unsigned char *moov_atom, info->trak_count--; return; } + break; + + case UDTA_ATOM: + parse_meta_atom(info, &moov_atom[i + 4]); + if (info->last_error != QT_OK) + return; + break; - } else if (current_atom == META_ATOM) { - + case META_ATOM: parse_meta_atom(info, &moov_atom[i - 4]); if (info->last_error != QT_OK) return; + break; - } else if (current_atom == NAM_ATOM) { - - string_size = BE_16(&moov_atom[i + 4]) + 1; + case NAM_ATOM: + string_size = _X_BE_16(&moov_atom[i + 4]) + 1; info->name = realloc (info->name, string_size); strncpy(info->name, &moov_atom[i + 8], string_size - 1); info->name[string_size - 1] = 0; + break; - } else if (current_atom == CPY_ATOM) { - - string_size = BE_16(&moov_atom[i + 4]) + 1; + case CPY_ATOM: + string_size = _X_BE_16(&moov_atom[i + 4]) + 1; info->copyright = realloc (info->copyright, string_size); strncpy(info->copyright, &moov_atom[i + 8], string_size - 1); info->copyright[string_size - 1] = 0; + break; - } else if (current_atom == DES_ATOM) { - - string_size = BE_16(&moov_atom[i + 4]) + 1; + case DES_ATOM: + string_size = _X_BE_16(&moov_atom[i + 4]) + 1; info->description = realloc (info->description, string_size); strncpy(info->description, &moov_atom[i + 8], string_size - 1); info->description[string_size - 1] = 0; + break; - } else if (current_atom == CMT_ATOM) { - - string_size = BE_16(&moov_atom[i + 4]) + 1; + case CMT_ATOM: + string_size = _X_BE_16(&moov_atom[i + 4]) + 1; info->comment = realloc (info->comment, string_size); strncpy(info->comment, &moov_atom[i + 8], string_size - 1); info->comment[string_size - 1] = 0; + break; - } else if (current_atom == RMDA_ATOM) { - + case RMDA_ATOM: + case RMRA_ATOM: /* create a new reference structure */ info->reference_count++; info->references = (reference_t *)realloc(info->references, @@ -1996,8 +2076,9 @@ static void parse_moov_atom(qt_info *info, unsigned char *moov_atom, parse_reference_atom(&info->references[info->reference_count - 1], &moov_atom[i - 4], info->base_mrl); + break; - } else { + default: debug_atom_load(" qt: unknown atom into the moov atom (0x%08X)\n", current_atom); } } @@ -2098,24 +2179,24 @@ static qt_error open_qt_file(qt_info *info, input_plugin_t *input, else { memset (&preview, 0, MAX_PREVIEW_SIZE); input->get_optional_data(input, preview, INPUT_OPTIONAL_DATA_PREVIEW); - if (BE_32(&preview[4]) != MOOV_ATOM) { + if (_X_BE_32(&preview[4]) != MOOV_ATOM) { /* special case if there is an ftyp atom first */ - if (BE_32(&preview[4]) == FTYP_ATOM) { - moov_atom_size = BE_32(&preview[0]); + if (_X_BE_32(&preview[4]) == FTYP_ATOM) { + moov_atom_size = _X_BE_32(&preview[0]); if ((moov_atom_size + ATOM_PREAMBLE_SIZE >= MAX_PREVIEW_SIZE) || - (BE_32(&preview[moov_atom_size + 4]) != MOOV_ATOM)) { + (_X_BE_32(&preview[moov_atom_size + 4]) != MOOV_ATOM)) { info->last_error = QT_NO_MOOV_ATOM; return info->last_error; } moov_atom_offset = moov_atom_size; - moov_atom_size = BE_32(&preview[moov_atom_offset]); + moov_atom_size = _X_BE_32(&preview[moov_atom_offset]); } else { info->last_error = QT_NO_MOOV_ATOM; return info->last_error; } } else { moov_atom_offset = 0; - moov_atom_size = BE_32(&preview[0]); + moov_atom_size = _X_BE_32(&preview[0]); } } @@ -2146,14 +2227,14 @@ static qt_error open_qt_file(qt_info *info, input_plugin_t *input, } /* check if moov is compressed */ - if (BE_32(&moov_atom[12]) == CMOV_ATOM) { + if (_X_BE_32(&moov_atom[12]) == CMOV_ATOM) { info->compressed_header = 1; z_state.next_in = &moov_atom[0x28]; z_state.avail_in = moov_atom_size - 0x28; - z_state.avail_out = BE_32(&moov_atom[0x24]); - unzip_buffer = (unsigned char *)malloc(BE_32(&moov_atom[0x24])); + z_state.avail_out = _X_BE_32(&moov_atom[0x24]); + unzip_buffer = (unsigned char *)malloc(_X_BE_32(&moov_atom[0x24])); if (!unzip_buffer) { free(moov_atom); info->last_error = QT_NO_MEMORY; @@ -2192,7 +2273,7 @@ static qt_error open_qt_file(qt_info *info, input_plugin_t *input, /* replace the compressed moov atom with the decompressed atom */ free (moov_atom); moov_atom = unzip_buffer; - moov_atom_size = BE_32(&moov_atom[0]); + moov_atom_size = _X_BE_32(&moov_atom[0]); } if (!moov_atom) { |