summaryrefslogtreecommitdiff
path: root/mp4.c (follow)
Commit message (Collapse)AuthorAge
* Fix gcc-16 warnings about unterminated strings.Andre Noll2026-05-24
| | | | | | | | | | | None of the four char arrays are C strings, and they are not supposed to be passed to functions like strcpy() which look for the first NUL byte. The nonstring attribute tells the compiler about this fact. Without it, gcc-16 complains, suggesting to annotate the affected variables with __attribute__ ((nonstring)). Unfortunately, at least clang-19.1.7 does not know this attribute and issues a warning, so we check at compile time whether $(CC) supports it and define __nonstring accordingly.
* Include regex.h from para.h.Andre Noll2025-05-19
| | | | Every .c file includes it anyway.
* Prevent doxygen from generating invalid html.Andre Noll2024-05-13
| | | | | Doxygen is too stupid to grok the preprocessor tricks we are playing here, so don't generate documentation for these parts.
* Compile with -Wsuggest-attribute=malloc.Andre Noll2023-12-24
| | | | | | | | | | | | We already employ this attribute extensively to help the compiler improve optimization. However, a few malloc-like functions were not yet marked with __malloc. Fix that and enable the warning to make sure that new malloc-like functions get marked. Since not all supported compilers know about this warning option, we need to check at compile time whether the option is supported. Thanks to the existing cc-option make(1) function, this is a simple one-liner for Makefile.real.
* Merge topic branch t/overflow into masterAndre Noll2022-10-03
| | | | | | | | | | | | | | | | | | | This series implements a new memory allocation API which checks for overflows. The first part of the series just renames the main allocation functions. Later patches in the series implement allocators which take two size_t arguments (like calloc(3)) and check whether the multiplication overflows by employing the __builtin_mul_overflow() primitive supported by gcc and clang. This requires us to bump the lowest supported gcc and clang version. * refs/heads/t/overflow: build: Compile with -ftrapv. string: Introduce arr_zalloc(). string: Introduce arr_alloc(). string: Introduce arr_realloc() and check for integer overflow. string: Rename para_calloc() -> zalloc(). string: Rename para_malloc() -> alloc(). string: Overhaul para_strdup().
* mp4: Document the purpose of each atom.Andre Noll2022-06-27
| | | | This gives the reader a rough idea about the atoms we care about.
* mp4: Doxify the public API.Andre Noll2022-06-27
| | | | | This adds doxygen comments to all public functions of the mp4 API and to the macros and enumerations of mp4.c.
* mp4: Check for missing metadata also for regular opens.Andre Noll2022-06-27
| | | | | | Since we allow to update the metadata of a file handle returned by mp4_open(), we should check for both types of opens that the file actually contains the udta, meta and ilst atoms.
* mp4: Rename mp4_open_read() to mp4_open().Andre Noll2022-06-27
| | | | | | | The function may be called with the intention to update the meta tags later by calling mp4_update_meta(), albeit mp4_open_meta() is cheaper if the caller only wants to modify the metadata. The old name is thus slightly misleading, and it's longer.
* mp4: Rename mp4_meta_update() to mp4_update_meta().Andre Noll2022-06-27
| | | | Just to be consistent with mp4_open_meta() and friends.
* mp4: Simplify mp4_num_samples().Andre Noll2022-06-27
| | | | | | We don't need to iterate over the entries of the stts_sample_count array because the number stored in the stsz_sample_count field should be identical to the sum of the sample counts.
* mp4: Reject files with zero time scale.Andre Noll2022-06-27
| | | | | | | | | | | | | A value of zero indicates a corrupt mp4 file or a missing mdhd atom. This is fatal because we need to divide by the time scale to compute the duration of the audio track. This patch modifies mp4_open_read() to check the value at open time and fail the operation rather than allowing the open to succeed and checking the value in mp4_get_duration(), Only regular opens are affected since we don't look at the mdhd atom for metadata opens.
* mp4: Assorted trivial cleanups.Andre Noll2022-06-27
| | | | | | Avoid C++ comments, use int rather than int32_t as the standard return type, kill a pointless cast and use plain unsigned rather than uint32_t for the number of tag items.
* mp4: Remove ->len member of struct mp4_tag.Andre Noll2022-06-27
| | | | It is set but never read.
* mp4: Fix possible memory leak on errors.Andre Noll2022-06-27
| | | | | | | | | | If the sanity checks in open_file() fail, we free the mp4 structure but not the various tables and metadata items we might already have allocated at this point. Fix this by calling mp4_close() instead of freeing the mp4 struct directly. We have to move mp4_close() above open_file() to avoid a forward declaration.
* mp4: Return proper types for sample rate and count.Andre Noll2022-06-27
| | | | | | The sample rate and the number of samples are stored as 16-bit/32-bit unsigned integers in the mp4 file, so let mp4_get_sample_rate() and mp4_num_samples() return these types.
* mp4: Fail early on invalid sample rate or sample count.Andre Noll2022-06-27
| | | | | | | | | | If the sample rate or the sample count happen to be zero, we should fail the open rather than return success and let the caller deal with it. This patch moves the corresponding sanity checks from aac_afh.c to mp4_open_read() of mp4.c. The sample rate is always read while sample count is skipped for metadata-only opens. So the first check belongs to the common open_file() while the second check needs to go to mp4_open_read().
* mp4: Remove E_MP4_BAD_CHANNEL_COUNT.Andre Noll2022-06-06
| | | | | | | | | | | If the mp4 file does not contain an m4a atom, the channel count stays at zero and open_file() returns -E_MP4_TRACK in this case. So the check in aac_afh.c for a non-positive return value from mp4_get_channel_count() can never trigger. Replace the check by an assertion and remove the error code. Also, let mp4_get_channel_count() return uint16_t as the number of channels is stored as an unsigned 16 bit number in the mp4 file.
* mp4: Improve mp4_get_sample_size().Andre Noll2022-06-06
| | | | | | Use an unsigned type for the sample number and check that the passed number is within range. Since the function can fail now, let it return int and return the sample size via an additional pointer argument.
* mp4: Make sample number be an unsigned parameter.Andre Noll2022-06-06
| | | | | | There is no reason to convert the 32-bit unsigned paraslash chunk number into a signed quantity here, as sample numbers are also stored as 32 bit unsigned in the mp4 file.
* mp4: Check the return value of ->truncate().Andre Noll2022-06-06
| | | | | | | This callback is implemented as a simple wrapper for the ftruncate() system call, which can fail for a number of reasons. Currently the callback returns unsigned and the return value is ignored. Fortunately, this is easy to fix.
* mp4: Make most loop variables unsigned.Andre Noll2022-06-06
| | | | | | | | | | | | | If the loop variable iterates from zero to some number stored in a variable of unsigned type, the loop variable should be of the same unsigned type. This was not always the case, and if it was, the loop variable was sometimes called i, which is confusing because i usually indicates a signed quantity. Quoting Andrew Morton: Doing "unsigned i;" is an act of insane vandalism, punishable by spending five additional years coding in fortran.
* mp4: Replace the five tag value functions by a single one.Andre Noll2022-06-06
| | | | | | | | | | It's easier to let the caller pass the tag item string than to have one caller for each of the five tags of interest. This commit renames meta_find_by_name() to mp4_get_tag_value(), makes it public and removes its five callers from mp4.c. The only user is _aac_afh_get_taginfo() of aac_afh.c, which needs to be adjusted accordingly. Kill the pointless underscore while at it.
* mp4: Provide proper error codes for all errors.Andre Noll2022-06-06
| | | | | | This changes the few remaining places where we return -1 to indicate failure by proper error codes which can be turned into a meaningful error message.
* mp4: Simplify atom_read_header().Andre Noll2022-06-06
| | | | | All callers pass non-NULL pointers for the atom size, so the condition which is removed in this commit is always true.
* mp4: Remove tracks array.Andre Noll2022-06-05
| | | | | | | | | | | | | | | | | | | | | | The mp4 structure currently contains an array of 1024 track pointers which are initialized to point to track structures allocated as we encounter tracks. This is kind of wasteful given that we will only care about audio tracks, and only ever consider the first one. This patch replaces the pointer array by a single track structure embedded within struct mp4. Besides the above mentioned memory savings, this approach allows us to remove a bunch of identical sanity checks in the atom parsers. The old code maintained the ->audio_track pointer of struct mp4 to tell whether we already saw an mp4a atom and thus already allocated a structure for the corresponding track. We now use a state based approach with three states instead. The state value determines whether we have to parse the atom. The first state transition takes place when the mp4a atom is encountered while the second transition occurs at the subsequent trak atom, if any. If an atom parser is called while the state machine is in an unexpected state, we return success rather than an error code to ignore the atom without failing the whole operation.
* mp4: Merge read_mp4a() into read_stsd().Andre Noll2022-05-30
| | | | | | | | This shortens the code because we already have a track pointer here and can get rid of the duplicated check for the number of tracks. The commit also adds the missing error check for the last read operation, i.e. the one which reads the sample rate.
* mp4: Introduce skip_bytes().Andre Noll2022-05-30
| | | | | | | | | | | | | | | | We often call one of the read_intX() helpers with a NULL result pointer just to move the file position forward. Calling ->seek() with whence set to SEEK_CUR is simpler and has the advantage that this operation cannot fail. If we happen to seek beyond EOF, the next read will return EOF and we'll abort then. This patch provides the skip_bytes() helper and replaces all read_intX(f, NULL) calls by calls to skip_bytes() and removes the error checking. Due to this cleanup read_int8() and read_int24() and read_u24_be() (the latter being an inline function defined in portable_io.h) have become unused, so remove these as well.
* mp4: Provide whence parameter for the seek callback.Andre Noll2022-05-30
| | | | | | | | | | | | | | | | | | This adds a parameter to make ->seek() work like the lseek(2) system call. This is easy to implement in both the memory-mapped callback case used to retrieve the file information and the metadata update case where ->seek() is a trivial wrapper for lseek(2). With the additional functionality in place we don't need to track the file size and the current file offset any more in mp4.c as these values can now be obtained by calling ->seek() with a zero offset and whence set to SEEK_END and SEEK_CUR, respectively. This also makes the code more robust against corrupt mp4 files because we no longer rely on the values from the atom headers to compute the file size. The way mp4.c calls ->seek() should never cause the underlying lseek(2) system call to fail. Therefore it suffices to check the return value only in the callback wrapper and abort on failure.
* mp4: Implement error checking for the write path.Andre Noll2022-05-30
| | | | | | | | | | | Although the ->write callback has a return value, it is of unsigned type and is never checked. Fix this by changing the prototype to match that of the write(2) system call, check the return value of the callback in the write_data() wrapper of mp4.c and propagate paraslash error codes back to aac_afh.c via the public mp4_meta_update(). While at it, handle short writes and EINTR properly, and fix the indentation of the callback structure in mp4.h.
* mp4: Merge write_int32() into mp4_meta_update().Andre Noll2022-05-30
| | | | | | It has only this single caller, and it's short. Use uint8_t instead of int8_t for the buffer as we do elsewhere and rename the buffer variable while at it.
* mp4: Simplify mp4_meta_update().Andre Noll2022-05-30
| | | | | Move duplicated common code out of the if/else branches and kill a pointless variable.
* mp4: Avoid camel case for members of struct mp4_track.Andre Noll2022-05-30
| | | | | | | | | Only three members of struct mp4 are in camel case while all others follow the underscore convention, which is the standard coding style of the paraslash code base. Let's be consistent here. Add comments which indicate the origin of the values stored while at it.
* mp4: Kill fix_byte_order_32().Andre Noll2022-05-30
| | | | | | All quantities stored in mp4 files are in big endian format, There's no reason to "fix" anything, just write out the 32 bit numbers using write_u32_be().
* mp4: Avoid duplicating the list of atoms.Andre Noll2022-05-30
| | | | | | A little cpp magic can do wonders in this regard. The new atom_name_to_type() should also be more efficient because we replaced four 8-bit comparisons by one 32-bit comparison.
* mp4: Merge parse_leaf_atom() into parse_sub_atoms().Andre Noll2022-05-30
| | | | | | | | | | This gets rid of the distinction between atoms with and without subatoms, which was confusing because some atoms "without" subatoms in fact do contain subatoms, we just did not want to parse them recursively in parse_sub_atoms(). With this weirdness gone, we may move on to simplify the atoms enum and atom_name_to_type() further, but this is left to a subsequent patch.
* mp4: Simplify parse_sub_atoms().Andre Noll2022-05-30
| | | | | | | This converts the while loop into a for loop and replaces the counted_size variable by "dest" to clarify the loop structure. We also move the two 8-bit variables into the loop as they are only used there and skip their pointless initializations.
* mp4: Use automatic numbering for atom enum.Andre Noll2022-05-30
| | | | | | | The exact numbers numbers of the ATOM enum are irrelevant. The only thing which matters is the distinction between atoms we are only interested in because they contain subatoms we care about and atoms for which there is a corresponding read_xxx() parser.
* mp4: Remove unused atoms.Andre Noll2022-05-30
| | | | | | The enum and atom_name_to_type() still knows about a lot of atoms we don't care about. These only clutter up the code and slow things down, so drop them.
* mp4: Kill membuffer API.Andre Noll2022-05-30
| | | | | | | | Thanks to the previous cleanups, create_ilst() is the last remaining membuffer user. Since the size of the ilst atom can be computed as the sum of the tag lengths plus a constant times the number of tag items, we can allocate a suitably sized buffer up-front instead of relying on the membuffer framework to allocate and resize buffers as needed.
* mp4: Assume udta, meta and ilst are always present.Andre Noll2022-05-30
| | | | | | | | | Under normal circumstances these atoms exist or can at least be created by other means (e.g., by running mp4tags -a foo bar.m4a). This patch makes mp4_open_meta() fail early if at least one of the three atoms is missing. This allows to remove the (never tested hence probably buggy) code which creates these atoms.
* mp4: Merge membuffer_write_std_tag() into create_ilst().Andre Noll2022-05-30
| | | | The former is short and is only called by the latter.
* mp4: Eliminate duplication between the two open functions.Andre Noll2022-05-30
| | | | | | | | | | | | The only difference between mp4_open_read() and mp4_open_meta() is that they pass different values for the meta_only flag to parse_root_atoms(). We can avoid some duplication by moving the common code to parse_root_atoms(). Rename that function to open_file() because it now does more than just parsing atoms. The patch also changes the prototype of both public open functions to return an integer error code in addition to the pointer to an mp4 structure. This allows us to gradually improve the error diagnostics.
* mp4: Remove find_atom() and find_atom_v2().Andre Noll2022-05-30
| | | | | | | | During mp4_open_meta() we encounter the ILST, META and UDTA atoms but don't record the size and the location of these atoms. Doing so allows us to use this information later in mp4_meta_update() instead of calling find_atom() or find_atom_v2() to search the file again. This removes some ugly code and speeds up the operation.
* mp4: Get rid of find_standard_meta().Andre Noll2022-05-30
| | | | | | | | | | | | | | | | | We don't need a dedicated function and data structure for that. Just open-code the logic in create_ilst() and clean up this function a bit while at it. Specifically: * Call the loop variable "n" rather than "metaptr" since it is not a pointer but an unsigned integer. * Abort if we encounter a tag item name which is not one of the five standard names. This can never occur because the origin of these strings is the code in aac_afh.c which only passes standard names. * Drop the integer return value, since the function can never fail. Make it return the buffer pointer instead and get rid of the corresponding parameter.
* mp4: Improve parse_tag().Andre Noll2022-05-30
| | | | | | | | | | | | | | | | * Merge tag_add_field() and read_string() into parse_tag() since they are simple enough and have only one caller. * Avoid memory leaks in the error case. * Let the function return an error code (rather than -1) in all cases, and check the return value in the callers. * Add a sanity check for the subsize. * Avoid creating two copies of the tag value. * Rename the variable for the tag value.
* mp4: Simplify read_mp4a().Andre Noll2022-05-30
| | | | | | The single caller resets the file offset after the call, so we may stop reading the atom after we've parsed the last field of interest, which happens to be the sample rate.
* mp4: Remove two local unused header_size variables.Andre Noll2022-05-30
| | | | | | The header size is an optional pointer argument of atom_read_header(), i.e., callers may pass NULL if they aren't interested in the atom header size.
* mp4: Rename atom_read() to parse_leaf_atom().Andre Noll2022-05-30
| | | | For consistency and symmetry with parse_subatoms().
* mp4: Reduce atom parsing to the bare minimum.Andre Noll2022-05-30
| | | | | | | | | This replaces need_parse_when_meta_only() by need_atom() which is called from parse_sub_atoms() for both regular opens and meta-only opens to decide if the detected atom needs to be parsed. After this patch we skip more atoms than we used to do, speeding up the operation for both kinds of opens.