paraslash.git
22 months agomp4: Replace the five tag value functions by a single one.
Andre Noll [Thu, 26 Aug 2021 17:57:45 +0000 (19:57 +0200)]
mp4: Replace the five tag value functions by a single one.

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.

22 months agomp4: Provide proper error codes for all errors.
Andre Noll [Thu, 26 Aug 2021 17:20:49 +0000 (19:20 +0200)]
mp4: Provide proper error codes for all errors.

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.

22 months agomp4: Simplify atom_read_header().
Andre Noll [Thu, 26 Aug 2021 17:05:28 +0000 (19:05 +0200)]
mp4: Simplify atom_read_header().

All callers pass non-NULL pointers for the atom size, so the condition
which is removed in this commit is always true.

22 months agomp4: Remove tracks array.
Andre Noll [Thu, 26 Aug 2021 16:36:00 +0000 (18:36 +0200)]
mp4: Remove tracks array.

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.

22 months agoRemove para_dirname() and para_basename().
Andre Noll [Fri, 11 Mar 2022 18:32:24 +0000 (19:32 +0100)]
Remove para_dirname() and para_basename().

The former has only a single caller, the second only two, open-coding
these is actually simpler and more performant because we no longer
scan each path twice and avoid the temporary copy of the path.

22 months agomp4: Merge read_mp4a() into read_stsd().
Andre Noll [Wed, 25 Aug 2021 16:41:07 +0000 (18:41 +0200)]
mp4: Merge read_mp4a() into read_stsd().

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.

22 months agomp4: Introduce skip_bytes().
Andre Noll [Tue, 24 Aug 2021 19:37:06 +0000 (21:37 +0200)]
mp4: Introduce skip_bytes().

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.

22 months agomp4: Provide whence parameter for the seek callback.
Andre Noll [Tue, 24 Aug 2021 18:47:03 +0000 (20:47 +0200)]
mp4: Provide whence parameter for the seek callback.

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.

22 months agomp4: Implement error checking for the write path.
Andre Noll [Tue, 24 Aug 2021 12:49:16 +0000 (14:49 +0200)]
mp4: Implement error checking for the write path.

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.

22 months agomp4: Merge write_int32() into mp4_meta_update().
Andre Noll [Mon, 23 Aug 2021 19:30:14 +0000 (21:30 +0200)]
mp4: Merge write_int32() into mp4_meta_update().

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.

22 months agomp4: Simplify mp4_meta_update().
Andre Noll [Mon, 23 Aug 2021 19:12:27 +0000 (21:12 +0200)]
mp4: Simplify mp4_meta_update().

Move duplicated common code out of the if/else branches and kill a
pointless variable.

22 months agomp4: Avoid camel case for members of struct mp4_track.
Andre Noll [Mon, 23 Aug 2021 18:18:54 +0000 (20:18 +0200)]
mp4: Avoid camel case for members of struct mp4_track.

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.

22 months agomp4: Kill fix_byte_order_32().
Andre Noll [Mon, 23 Aug 2021 18:12:30 +0000 (20:12 +0200)]
mp4: Kill fix_byte_order_32().

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().

22 months agomp4: Avoid duplicating the list of atoms.
Andre Noll [Mon, 23 Aug 2021 14:37:33 +0000 (16:37 +0200)]
mp4: Avoid duplicating the list of atoms.

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.

22 months agomp4: Merge parse_leaf_atom() into parse_sub_atoms().
Andre Noll [Mon, 23 Aug 2021 14:24:38 +0000 (16:24 +0200)]
mp4: Merge parse_leaf_atom() into parse_sub_atoms().

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.

22 months agomp4: Simplify parse_sub_atoms().
Andre Noll [Mon, 23 Aug 2021 14:18:17 +0000 (16:18 +0200)]
mp4: Simplify parse_sub_atoms().

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.

22 months agomp4: Use automatic numbering for atom enum.
Andre Noll [Sun, 22 Aug 2021 21:08:36 +0000 (23:08 +0200)]
mp4: Use automatic numbering for atom enum.

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.

22 months agomp4: Remove unused atoms.
Andre Noll [Sun, 22 Aug 2021 20:49:13 +0000 (22:49 +0200)]
mp4: Remove unused atoms.

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.

22 months agomp4: Kill membuffer API.
Andre Noll [Sun, 22 Aug 2021 19:16:48 +0000 (21:16 +0200)]
mp4: Kill membuffer API.

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.

22 months agomp4: Assume udta, meta and ilst are always present.
Andre Noll [Sun, 22 Aug 2021 18:01:01 +0000 (20:01 +0200)]
mp4: Assume udta, meta and ilst are always present.

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.

22 months agomp4: Merge membuffer_write_std_tag() into create_ilst().
Andre Noll [Sat, 21 Aug 2021 17:28:52 +0000 (19:28 +0200)]
mp4: Merge membuffer_write_std_tag() into create_ilst().

The former is short and is only called by the latter.

22 months agomp4: Eliminate duplication between the two open functions.
Andre Noll [Sat, 21 Aug 2021 15:56:17 +0000 (17:56 +0200)]
mp4: Eliminate duplication between the two open functions.

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.

22 months agomp4: Remove find_atom() and find_atom_v2().
Andre Noll [Sat, 21 Aug 2021 14:23:05 +0000 (16:23 +0200)]
mp4: Remove find_atom() and find_atom_v2().

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.

22 months agomp4: Get rid of find_standard_meta().
Andre Noll [Sat, 21 Aug 2021 11:30:02 +0000 (13:30 +0200)]
mp4: Get rid of find_standard_meta().

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.

22 months agomp4: Improve parse_tag().
Andre Noll [Fri, 20 Aug 2021 12:23:04 +0000 (14:23 +0200)]
mp4: Improve parse_tag().

* 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.

22 months agomp4: Simplify read_mp4a().
Andre Noll [Fri, 20 Aug 2021 11:38:55 +0000 (13:38 +0200)]
mp4: Simplify read_mp4a().

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.

22 months agomp4: Remove two local unused header_size variables.
Andre Noll [Fri, 20 Aug 2021 11:33:17 +0000 (13:33 +0200)]
mp4: Remove two local unused header_size variables.

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.

22 months agomp4: Rename atom_read() to parse_leaf_atom().
Andre Noll [Thu, 19 Aug 2021 18:13:57 +0000 (20:13 +0200)]
mp4: Rename atom_read() to parse_leaf_atom().

For consistency and symmetry with parse_subatoms().

22 months agomp4: Reduce atom parsing to the bare minimum.
Andre Noll [Thu, 19 Aug 2021 18:07:13 +0000 (20:07 +0200)]
mp4: Reduce atom parsing to the bare minimum.

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.

22 months agomp4: Convert "meta_only" to a boolean.
Andre Noll [Thu, 19 Aug 2021 17:13:31 +0000 (19:13 +0200)]
mp4: Convert "meta_only" to a boolean.

Several functions receive the "meta_only" parameter to distinguish
between regular and metadata-only opens. The parameter can only be
zero or one, so use a boolean because true/false is more descriptive
than 1/0.

22 months agomp4: Simplify parse_atoms().
Andre Noll [Thu, 19 Aug 2021 17:06:10 +0000 (19:06 +0200)]
mp4: Simplify parse_atoms().

We are only interested in subatoms of the moov atom, so skip everything
else. Rename the function to parse_root_atoms() and remove the comment
which does not convey any information anymore.

22 months agomp4: Remove two unused arrays from struct mp4_track.
Andre Noll [Thu, 19 Aug 2021 14:08:46 +0000 (16:08 +0200)]
mp4: Remove two unused arrays from struct mp4_track.

These arrays are allocated and initialized but their values are
never read.

22 months agomp4: Hide tracks array.
Andre Noll [Thu, 19 Aug 2021 13:52:13 +0000 (15:52 +0200)]
mp4: Hide tracks array.

All functions of mp4.c operate on the first audio track. This
patch makes this fact implicit which allows us to remove the public
mp4_get_total_tracks() and mp4_is_audio_track(). Moreover, the track
parameter can be removed from all public functions.

If no audio track was found in the mp4 file, we now return an error
from two public open functions of mp4.c. Otherwise, we maintain a
pointer to the first audio track within the mp4 structure and use
that to identify the track rather than letting the API users pass
the track number.

22 months agomp4: Simplify chunk_of_sample().
Andre Noll [Wed, 18 Aug 2021 21:15:07 +0000 (23:15 +0200)]
mp4: Simplify chunk_of_sample().

This function was unnecessarily complex. The equivalent replacement
code is much shorter and easier to read. Besides reducing the number
of local variables, we drop the chunk_sample parameter and return
this number via the return value of the function.

22 months agomp4: Merge chunk_to_offset() into mp4_set_sample_position().
Andre Noll [Wed, 18 Aug 2021 19:18:29 +0000 (21:18 +0200)]
mp4: Merge chunk_to_offset() into mp4_set_sample_position().

Another equivalent transformation which shortens the code and improves
readability.

22 months agomp4: Merge sample_range_size() into mp4_set_sample_position().
Andre Noll [Wed, 18 Aug 2021 19:08:45 +0000 (21:08 +0200)]
mp4: Merge sample_range_size() into mp4_set_sample_position().

This equivalent transformation shortens the code and improves
readability.

22 months agomp4: Provide return value for mp4_set_sample_position().
Andre Noll [Wed, 18 Aug 2021 18:59:25 +0000 (20:59 +0200)]
mp4: Provide return value for mp4_set_sample_position().

This function fails if the given parameters are invalid. Detect this
and return EINVAL in this case. Add corresponding error checking to
the aac audio format handler.

22 months agomp4: Simplify sample_range_size().
Andre Noll [Wed, 18 Aug 2021 18:46:52 +0000 (20:46 +0200)]
mp4: Simplify sample_range_size().

Reduce indentation by making the else branch unconditional and simply
call the track pointer "t" rather than "p_track".

22 months agomp4: Merge sample_to_offset() into mp4_set_sample_position().
Andre Noll [Wed, 18 Aug 2021 18:36:50 +0000 (20:36 +0200)]
mp4: Merge sample_to_offset() into mp4_set_sample_position().

The former is only called by the latter, and both are
short. De-obfuscate the code a little by avoiding pointless local
variables.

22 months agomp4: Rename mp4_total_tracks() to mp4_get_total_tracks().
Andre Noll [Wed, 18 Aug 2021 16:12:44 +0000 (18:12 +0200)]
mp4: Rename mp4_total_tracks() to mp4_get_total_tracks().

Just to be consistent with other public functions whose name contain
a predicate. Move the function down to related functions.

22 months agomp4: Remove ->error of struct mp4.
Andre Noll [Wed, 18 Aug 2021 16:08:38 +0000 (18:08 +0200)]
mp4: Remove ->error of struct mp4.

It's easier to have track_add(), the only function which sets ->error,
return an integer error code instead. Since track_add() is simple
and is only called by parse_sub_atoms(), open-code the logic there.

Also, don't reset ->total_tracks on errors because this leads to a
memory leak, don't increase the track counter on errors and remove
the comment which only states what is obvious.

22 months agomp4: Add error checking to parse_atoms() and friends.
Andre Noll [Wed, 18 Aug 2021 15:08:08 +0000 (17:08 +0200)]
mp4: Add error checking to parse_atoms() and friends.

After this patch read errors are propagated all the way down from the
read_data() primitive to the public entry functions mp4_open_read()
and mp4_open_meta().

22 months agomp4: Add error checking for atom_read().
Andre Noll [Wed, 18 Aug 2021 14:59:35 +0000 (16:59 +0200)]
mp4: Add error checking for atom_read().

While the individual atom parsers all perform error checking and
return an error code, their caller, atom_read(), ignores errors.

Address this shortcoming, simplify the function by using a switch
instead of an if-else chain and move the descriptions of the atoms
to the enum where they belong.

22 months agomp4: Improve handling of read errors.
Andre Noll [Wed, 18 Aug 2021 13:25:17 +0000 (15:25 +0200)]
mp4: Improve handling of read errors.

Currently read_data() of mp4.c is an atrocious mess. The ->read()
callback is defined to return uint32_t, but the return value is
stored in a signed 32 bit integer. Moreover, read_data() contains a
dead store, it handles neither short nor interrupted reads correctly,
and it moves the file position backwards on errors.

While this is easy to fix, a more intricate problem is that most
callers of read_data(), including all read_intX() helpers, ignore the
return value of read_data() and return uninitialized stack contents in
the error case. This is kind of dealt with by the ->read_error member
of struct mp4, but this not more than a kludge, which, according to
the comments, was applied after several CVEs had been filed against
the library.

Let's DTRT here, even though it adds a fair amount of new code:
Check the return value of each read operation and fail early on errors.

We have to distinguish three cases: error, EOF, and success, encoded
as return values -1, 0 and 1, respectively. This commit converts most
functions which read from an mp4 file to this convention. More work
is required as return values are not checked everywhere yet. This was
left for subsequent commits to keep the already large patch within
reasonable size.

Since we don't rely on ->read_error of struct mp4 any more, it can
be removed.

22 months agomp4: Remove dead store from find_atom_v2().
Andre Noll [Wed, 18 Aug 2021 13:15:41 +0000 (15:15 +0200)]
mp4: Remove dead store from find_atom_v2().

The "size" variable is not used in the code which follows the loop
we are breaking out here.

22 months agomp4: Move read_intX functions.
Andre Noll [Wed, 18 Aug 2021 13:11:09 +0000 (15:11 +0200)]
mp4: Move read_intX functions.

This way, they are located next to each other, and are ordered by the
size of the integer value they read.

Pure code movement, no real changes.

22 months agomp4: Rename read_char() to read_int8().
Andre Noll [Wed, 18 Aug 2021 13:08:25 +0000 (15:08 +0200)]
mp4: Rename read_char() to read_int8().

That's more to the point, and is consistent with the other functions
which read integer values.

22 months agomp4: Make channel count a 16 bit quantity.
Andre Noll [Wed, 18 Aug 2021 13:05:09 +0000 (15:05 +0200)]
mp4: Make channel count a 16 bit quantity.

It gets initialized by reading an 16 bit integer.

22 months agomp4: Make most members of struct mp4_track unsigned.
Andre Noll [Wed, 18 Aug 2021 13:02:43 +0000 (15:02 +0200)]
mp4: Make most members of struct mp4_track unsigned.

All of these get initialized by reading an unsigned 32 bit value from
the file, so they should also be unsigned.

22 months agomp4: Merge membuffer_free() into membuffer_transfer_from_file().
Andre Noll [Sat, 14 Aug 2021 21:20:15 +0000 (23:20 +0200)]
mp4: Merge membuffer_free() into membuffer_transfer_from_file().

The latter is the only caller of the former.

22 months agomp4: Clean up membuffer_transfer_from_file().
Andre Noll [Sat, 14 Aug 2021 21:14:38 +0000 (23:14 +0200)]
mp4: Clean up membuffer_transfer_from_file().

The buffer pointer can never be NULL, so drop this check. Next, instead
of defining a void * pointer and cast it to char *, use char * directly.
Finally, the cast to unsigned has no effect, so drop it.

22 months agomp4: Drop return value from membuffer_write() and friends.
Andre Noll [Sat, 14 Aug 2021 21:07:11 +0000 (23:07 +0200)]
mp4: Drop return value from membuffer_write() and friends.

This function always returns the value it received via the last
argument. Pointless.

22 months agomp4: Remove the membuffer error bit.
Andre Noll [Sat, 14 Aug 2021 20:53:39 +0000 (22:53 +0200)]
mp4: Remove the membuffer error bit.

Due to the previous cleanups, it is never set, so remove all code
which checks whether the bit is set.

22 months agomp4: Free the membuffer in membuffer_detach().
Andre Noll [Sat, 14 Aug 2021 20:46:50 +0000 (22:46 +0200)]
mp4: Free the membuffer in membuffer_detach().

Each call to this function is followed by a call to membuffer_free(),
which frees the membuffer but not the data buffer because that was
set to NULL.

It is simpler to free the membuffer directly in membuffer_detach().

22 months agomp4: Simplify membuffer_create().
Andre Noll [Sat, 14 Aug 2021 20:40:00 +0000 (22:40 +0200)]
mp4: Simplify membuffer_create().

Since para_malloc() never returns NULL, the error state can only be
zero. Use para_calloc(), skip the zero initializations and kill a
pointless local variable.

22 months agomp4: Check return value of membuffer_transfer_from_file().
Andre Noll [Sat, 14 Aug 2021 20:27:12 +0000 (22:27 +0200)]
mp4: Check return value of membuffer_transfer_from_file().

This function calls the ->read() method of the callback, which may
fail. Currently all three callers ignore the return value and rely
on the fact that the membuffer is set to error state, which will be
detected later.

It's easier and clearer to check for errors in the callers and fail
early on read errors. Since the membuffer is useless in the error
case, free it right away in membuffer_transfer_from_file(). Change
the function to return bool instead of unsigned while at it and remove
a pointless cast in one of its callers.

22 months agomp4: Drop integer return type from modify_moov().
Andre Noll [Sat, 14 Aug 2021 18:53:15 +0000 (20:53 +0200)]
mp4: Drop integer return type from modify_moov().

This function returns either zero or one to indicate success. On
success, a pointer to a buffer and the buffer size are returned. It
is simpler and less redundant to indicate failure by returning a NULL
buffer pointer. Rather than using a void ** argument for the buffer,
let the function return void *.

22 months agomp4: Reduce indentation in modify_moov().
Andre Noll [Sat, 14 Aug 2021 18:42:55 +0000 (20:42 +0200)]
mp4: Reduce indentation in modify_moov().

If the condition of the if clause is true, we return early, so
the else clause can be made unconditional.

No real change.

22 months agomp4: Merge mp4_close() and tag_delete().
Andre Noll [Sat, 14 Aug 2021 18:21:51 +0000 (20:21 +0200)]
mp4: Merge mp4_close() and tag_delete().

The latter is only called by the former, and both are short enough.
Don't bother to zero out meta->tags and meta->count because we free
the containing mp4 structure as well.

22 months agomp4: Rename parse_metadata() to read_ilst().
Andre Noll [Sat, 14 Aug 2021 18:14:51 +0000 (20:14 +0200)]
mp4: Rename parse_metadata() to read_ilst().

To make the naming consistent with the other atom parsers. Kill
a pointless cast and unnecessary braces in the caller while at it.

22 months agomp4: Clean up membuffer_write_std_tag().
Andre Noll [Sat, 14 Aug 2021 17:38:21 +0000 (19:38 +0200)]
mp4: Clean up membuffer_write_std_tag().

Remove the check for the compilation flag since we never pass "cpil"
to this function. Remove the flags variable whose value is now always
one. Introduce a variable for the string length instead of calling
strlen() three times, and unify the way comments are formatted.

22 months agomp4: Clean up find_standard_meta().
Andre Noll [Sat, 14 Aug 2021 17:22:17 +0000 (19:22 +0200)]
mp4: Clean up find_standard_meta().

Use ARRAY_SIZE() instead of open-coding it, move the stdmetas array
into the function since it is only used there, and make it const.
Also replace 0 by NULL, since the function returns a pointer, and
remove the pointless comment.

Finally, move the function and the declaration of the stdmeta_entry
structure closer to its single user.

22 months agomp4: Simplify create_ilst().
Andre Noll [Sat, 14 Aug 2021 17:15:29 +0000 (19:15 +0200)]
mp4: Simplify create_ilst().

This function contains a lot of overhead which is just dead code
for paraslash since we only care about five standard tags, In
particular, we never write custom tags. Removing the single caller
of membuffer_write_custom_tag() left a whole bunch of other functions
and data structures unused, so these can be removed as well.

22 months agomp4: Call metadata structures "meta".
Andre Noll [Sat, 14 Aug 2021 17:00:06 +0000 (19:00 +0200)]
mp4: Call metadata structures "meta".

Currently they are called "tags" or "data", both of which are confusing
because struct mp4_metadata has a member called "tags", and "data"
is also used for generic buffers in the various I/O helpers.

22 months agoaac_afh: Simplify aac_afh_rewrite_tags().
Andre Noll [Thu, 19 Aug 2021 20:13:47 +0000 (22:13 +0200)]
aac_afh: Simplify aac_afh_rewrite_tags().

This function was disgusting because it listed the five standard
tags in three different ways. The new replace_or_add_tag() avoids
this issue.

22 months agomp4: Drop metadata parameter from mp4_meta_update().
Andre Noll [Sat, 14 Aug 2021 16:48:56 +0000 (18:48 +0200)]
mp4: Drop metadata parameter from mp4_meta_update().

The function can as well access the modified metadata structure via
the mp4 pointer. Drop the parameter also from modify_moov() for the
same reason.

22 months agomp4: Introduce mp4_get_meta().
Andre Noll [Sat, 14 Aug 2021 16:42:16 +0000 (18:42 +0200)]
mp4: Introduce mp4_get_meta().

Simplify the API by returning a pointer to the metadata structure stored
inside struct mp4. This is easier than having two accessor functions.

22 months agomp4: Simplify and speed up metadata editing.
Andre Noll [Sat, 14 Aug 2021 15:53:59 +0000 (17:53 +0200)]
mp4: Simplify and speed up metadata editing.

Currently the aac audio format handler first calls mp4_open_meta()
to get the metadata tags, then alters the in-memory structure of the
tags according to the command line options and passes this modified
structure to mp4_meta_update() to rewrite the tags. This latter call
parses the tags again, which is unnecessary overhead.

This patch changes the signature of mp4_meta_update() to accept an
mp4 structure instead of a callback structure and uses that instead
of re-opening the file.

22 months agomp4: Fix memory leak in mp4_meta_update().
Andre Noll [Fri, 13 Aug 2021 20:00:32 +0000 (22:00 +0200)]
mp4: Fix memory leak in mp4_meta_update().

This function calls modify_moov() which allocates and returns a
possibly large buffer, but this buffer is never freed.

Found by valgrind.

22 months agomp4: Simplify and doxify meta tag accessors.
Andre Noll [Fri, 13 Aug 2021 18:51:38 +0000 (20:51 +0200)]
mp4: Simplify and doxify meta tag accessors.

The integer return value is redundant, so get rid of the value
parameter and simplify meta_find_by_name() accordingly. Document that
tag values are allocated on the heap and should be freed by the caller.

22 months agomp4: Simplify parse_tag().
Andre Noll [Fri, 13 Aug 2021 18:19:43 +0000 (20:19 +0200)]
mp4: Simplify parse_tag().

We don't care about arbitrarily named tags, and those tags we're
interested in are generally present in form of the standard tags
(ATOM_TITLE, ATOM_ARTIST etc.).

Since we now always call get_metadata_name() to get the string
representation of the tag, we don't need to make a copy any more,
just pass the const pointer directly to tag_add_field().

With this change in place it is obvious that we never pass a NULL or
empty tag name to tag_add_field(), and we don't pass a NULL pointer
for the value argument either, so remove the safety check.

22 months agomp4: Simplify parse_tag().
Andre Noll [Thu, 12 Aug 2021 17:32:51 +0000 (19:32 +0200)]
mp4: Simplify parse_tag().

paraslash fundamentally cares only about five metatags. So remove
all code from parse_tag() which handles the tags we don't care about.

22 months agomp4: Rename and simplify set_metadata_name()
Andre Noll [Wed, 11 Aug 2021 20:52:11 +0000 (22:52 +0200)]
mp4: Rename and simplify set_metadata_name()

This function is an atrocious mess. For one, the naming is confusing
because the function does not set the atom name, it *returns* it.
More importantly, the function defines a static array for no good
reason and then hard-codes the array indices in a large switch
statement.

It's much easier to simply return a pointer to a string literal and
perform the strdup operation in the single caller.

22 months agomp4: Mark callback function pointers as const.
Andre Noll [Wed, 11 Aug 2021 19:56:09 +0000 (21:56 +0200)]
mp4: Mark callback function pointers as const.

The code in mp4.c never modifies any of the members of the callback
structure.

22 months agomp4: Use uniform names for callback and mp4 structures.
Andre Noll [Wed, 11 Aug 2021 19:45:12 +0000 (21:45 +0200)]
mp4: Use uniform names for callback and mp4 structures.

Currently it's a confusing mess, with callbacks called f, ff, or
stream, where the former two are also used for pointers to struct
mp4. Let's call a spade a spade and use cb everywhere for the callbacks
while f is reserved to denote an mp4 pointer.

22 months agomp4: Hide ->read_error.
Andre Noll [Wed, 11 Aug 2021 19:37:16 +0000 (21:37 +0200)]
mp4: Hide ->read_error.

This does not belong into the callback structure whose fields are
supposed to get initialized by the audio format handler. Move it to
the internal struct mp4 instead, next to the existing error counter.

22 months agomp4: Open-code pointless truncate_stream().
Andre Noll [Wed, 11 Aug 2021 19:30:14 +0000 (21:30 +0200)]
mp4: Open-code pointless truncate_stream().

This trivial one-liner has only a single caller.

22 months agomp4: Don't store the sample size in the mp4 structure.
Andre Noll [Wed, 11 Aug 2021 19:14:06 +0000 (21:14 +0200)]
mp4: Don't store the sample size in the mp4 structure.

Currently it is set but never read. We need to keep the read_int16()
call, however, to advance the file offset.

22 months agomp4: Don't store the stsd entry count.
Andre Noll [Wed, 11 Aug 2021 19:12:13 +0000 (21:12 +0200)]
mp4: Don't store the stsd entry count.

A local variable in read_stsd() will do as well.

22 months agomp4: Remove two unused fields of struct mp4.
Andre Noll [Wed, 11 Aug 2021 19:04:38 +0000 (21:04 +0200)]
mp4: Remove two unused fields of struct mp4.

These are neither set nor read.

22 months agomp4: Don't parse the ctts atom any more.
Andre Noll [Wed, 11 Aug 2021 19:02:33 +0000 (21:02 +0200)]
mp4: Don't parse the ctts atom any more.

The ctts sample offsets are useless for paraslash, so get rid of
the parser.

22 months agomp4: Don't parse the movie header any more.
Andre Noll [Wed, 11 Aug 2021 18:49:21 +0000 (20:49 +0200)]
mp4: Don't parse the movie header any more.

The duration and time scale are taken from the audio track while the
values stored in the movie header (if present) are ignored anyway.

22 months agomp4: Simplify atom_compare().
Andre Noll [Wed, 11 Aug 2021 17:40:03 +0000 (19:40 +0200)]
mp4: Simplify atom_compare().

No need for a condition here. Change the return type to bool, and
remove the pointless and misspelt comment.

22 months agomp4: Don't store track type anymore.
Andre Noll [Wed, 11 Aug 2021 17:36:59 +0000 (19:36 +0200)]
mp4: Don't store track type anymore.

The only thing we care about is whether or not a track is an audio
track. Hence a simple boolean suffices and the "tracks" enum can
be removed.

22 months agomp4: Don't parse the esds atom any more.
Andre Noll [Wed, 11 Aug 2021 17:26:00 +0000 (19:26 +0200)]
mp4: Don't parse the esds atom any more.

With the decoder specific config no longer in use, we can simplify
mp4.c further by getting rid of some cryptic and underdocumented code
which no longer does anything useful for us.

22 months agomp4: Introduce mp4_is_audio_track().
Andre Noll [Wed, 11 Aug 2021 17:12:07 +0000 (19:12 +0200)]
mp4: Introduce mp4_is_audio_track().

Currently the aac audio format handler iterates over the tracks
in an mp4 file. For each track it tries to get the audio-specific
configuration by calling mp4_get_decoder_config() and calls into faad
to check whether it is a valid configuration for the aac decoder.

We can simplify all this because the mp4 code already knows the type
of each track, albeit it does not expose this information yet. So
provide the new mp4_is_audio_track() helper and let the aac audio
format handler pick the first track for which this helper returns true.

As an additional benefit, we can remove the now unused
mp4_get_decoder_config().

22 months agomp4: Replace mp4ff prefix by mp4.
Andre Noll [Wed, 11 Aug 2021 16:31:55 +0000 (18:31 +0200)]
mp4: Replace mp4ff prefix by mp4.

The additional "ff" does not convey any useful information.

This patch was produced by running

sed -i 's/mp4ff/mp4/g' mp4.c mp4.h aac_afh.c

followed by

sed -i 's/MP4FF/MP4/g' aac_afh.c error.h

and the manual removal of the "ff" suffix in the error strings.

22 months agomp4: Rename mp4ff_open_read_metaonly() -> mp4ff_open_meta().
Andre Noll [Wed, 11 Aug 2021 14:56:57 +0000 (16:56 +0200)]
mp4: Rename mp4ff_open_read_metaonly() -> mp4ff_open_meta().

The old name is misleading because the returned file handle is by no
means opened read-only. In fact we call mp4ff_meta_update() on it,
which alters the file to store the modified metadata.

22 months agomp4: Introduce mp4ff_get_duration().
Andre Noll [Wed, 11 Aug 2021 13:41:37 +0000 (15:41 +0200)]
mp4: Introduce mp4ff_get_duration().

This allows us to get rid of an ugly hack in aac_afh.c where we peeked
at the audio-specific config structure to get the scaling factor which
was needed to compute the duration.

22 months agomp4: Prefer para_realloc() over plain realloc().
Andre Noll [Tue, 10 Aug 2021 17:08:41 +0000 (19:08 +0200)]
mp4: Prefer para_realloc() over plain realloc().

This allows us to skip the NULL check, which simplifies the code a bit.

22 months agomp4: Remove const qualifier from non-pointer function arguments.
Andre Noll [Tue, 10 Aug 2021 16:57:42 +0000 (18:57 +0200)]
mp4: Remove const qualifier from non-pointer function arguments.

In contrast to the pointer case, it's generally not very interesting
to know whether a function will modify the automatic variable which
corresponds to a non-pointer argument.

22 months agomp4: Whitespace and indentation cleanups for create_ilst().
Andre Noll [Mon, 9 Aug 2021 22:23:52 +0000 (00:23 +0200)]
mp4: Whitespace and indentation cleanups for create_ilst().

The only non-trivial cleanup is the reversed logic to reduce the
indentation of the code in the body of the for loop.

22 months agomp4: Remove pointless casts in create_ilst().
Andre Noll [Mon, 9 Aug 2021 22:19:56 +0000 (00:19 +0200)]
mp4: Remove pointless casts in create_ilst().

They have no effect because membuffer_write_int16_tag() takes a
unit16_t value anyway.

22 months agomp4: Reduce indentation of create_ilst().
Andre Noll [Mon, 9 Aug 2021 22:14:53 +0000 (00:14 +0200)]
mp4: Reduce indentation of create_ilst().

This function contained an indented block for no good reason. No real
change except that a few variables are exposed to the code below the
former block, but this is not a problem.

22 months agomp4: Kill pointless stricmp macro.
Andre Noll [Mon, 9 Aug 2021 22:12:31 +0000 (00:12 +0200)]
mp4: Kill pointless stricmp macro.

Just call strcasecmp() directly.

22 months agomp4: Make struct mp4ff opaque, hide struct mp4ff_track.
Andre Noll [Mon, 9 Aug 2021 22:06:48 +0000 (00:06 +0200)]
mp4: Make struct mp4ff opaque, hide struct mp4ff_track.

For the former, code outside of mp4.c only needs a pointer while the
latter does not need to be exposed at all.

Fix the indentation of the two declarations while at it.

22 months agomp4: Avoid typedefs for data structures.
Andre Noll [Mon, 9 Aug 2021 21:55:12 +0000 (23:55 +0200)]
mp4: Avoid typedefs for data structures.

They only obfuscate the type.

22 months agomp4: Fix trivial coding style issues in read_mvhd().
Andre Noll [Mon, 9 Aug 2021 21:31:38 +0000 (23:31 +0200)]
mp4: Fix trivial coding style issues in read_mvhd().

Some comments were located before the corresponding read statement,
some after, and some comments were indented weirdly.

No real change.

22 months agomp4: Prefer enums over defines.
Andre Noll [Mon, 9 Aug 2021 21:24:26 +0000 (23:24 +0200)]
mp4: Prefer enums over defines.

Just because the long list of macros clutters the taglist window
in vim.

22 months agomp4: Use read/write functions from portable_io.h.
Andre Noll [Mon, 9 Aug 2021 21:13:35 +0000 (23:13 +0200)]
mp4: Use read/write functions from portable_io.h.

This removes quite a bit of ugly code. In particular, atom_get_size()
is completely unnecessary and can be removed. Since there is no
function in portable_io.h to read a 24 bit integer, we have to add
read_u24_be().