]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
The mp4 tagger.
authorAndre Noll <maan@systemlinux.org>
Thu, 17 Apr 2014 21:16:11 +0000 (21:16 +0000)
committerAndre Noll <maan@tuebingen.mpg.de>
Sun, 26 Apr 2015 12:13:34 +0000 (14:13 +0200)
This commit adds support for editing meta tags of mp4 files. We
employ the mp4v2 library to do the work, so fairly little code has
to be added to the aac audio format handler.

We could deactivate tag editing for mp4 files if libmp4v2 was not
detected, but since subsequent commits for the aac audio format
handler will be based on the mp4v2 library as well, we keep it simple
and deactivate aac support completely in this case.

Makefile.in
Makefile.real
aac_afh.c
configure.ac
error.h

index 6d86ee7e7568a1bb940f1fb864af2327638c0ceb..c1b5e1dcae0b7391ca31a81cfe46e494c30a131b 100644 (file)
@@ -51,6 +51,7 @@ samplerate_cppflags := @samplerate_cppflags@
 readline_cppflags := @readline_cppflags@
 alsa_cppflags := @alsa_cppflags@
 oss_cppflags := @oss_cppflags@
 readline_cppflags := @readline_cppflags@
 alsa_cppflags := @alsa_cppflags@
 oss_cppflags := @oss_cppflags@
+mp4v2_cppflags := @mp4v2_cppflags@
 
 clock_gettime_ldflags := @clock_gettime_ldflags@
 id3tag_ldflags := @id3tag_ldflags@
 
 clock_gettime_ldflags := @clock_gettime_ldflags@
 id3tag_ldflags := @id3tag_ldflags@
@@ -74,5 +75,6 @@ curses_ldflags := @curses_ldflags@
 core_audio_ldflags := @core_audio_ldflags@
 crypto_ldflags := @crypto_ldflags@
 iconv_ldflags := @iconv_ldflags@
 core_audio_ldflags := @core_audio_ldflags@
 crypto_ldflags := @crypto_ldflags@
 iconv_ldflags := @iconv_ldflags@
+mp4v2_ldflags := @mp4v2_ldflags@
 
 include Makefile.real
 
 include Makefile.real
index fa8a915025e36c3bb5b42862f7f876c482ded184..0870f2edd2a81fc7afa1d7451c278a920e57f6a8 100644 (file)
@@ -196,6 +196,8 @@ $(object_dir)/flac%.o $(dep_dir)/flac%.d: CPPFLAGS += $(flac_cppflags)
 $(object_dir)/mp3_afh.o $(dep_dir)/mp3_afh.d: CPPFLAGS += $(id3tag_cppflags)
 $(object_dir)/crypt.o $(dep_dir)/crypt.d: CPPFLAGS += $(openssl_cppflags)
 $(object_dir)/gcrypt.o $(dep_dir)/gcrypt.d: CPPFLAGS += $(gcrypt_cppflags)
 $(object_dir)/mp3_afh.o $(dep_dir)/mp3_afh.d: CPPFLAGS += $(id3tag_cppflags)
 $(object_dir)/crypt.o $(dep_dir)/crypt.d: CPPFLAGS += $(openssl_cppflags)
 $(object_dir)/gcrypt.o $(dep_dir)/gcrypt.d: CPPFLAGS += $(gcrypt_cppflags)
+$(object_dir)/ao_write.o $(dep_dir)/ao_write.d: CPPFLAGS += $(ao_cppflags)
+$(object_dir)/aac_afh.o $(dep_dir)/aac_afh.d: CPPFLAGS += $(mp4v2_cppflags)
 $(object_dir)/alsa%.o $(dep_dir)/alsa%.d: CPPFLAGS += $(alsa_cppflags)
 
 $(object_dir)/interactive.o $(dep_dir)/interactive.d \
 $(object_dir)/alsa%.o $(dep_dir)/alsa%.d: CPPFLAGS += $(alsa_cppflags)
 
 $(object_dir)/interactive.o $(dep_dir)/interactive.d \
@@ -286,6 +288,7 @@ para_filter \
 para_play \
 : LDFLAGS += \
        $(mad_ldflags) \
 para_play \
 : LDFLAGS += \
        $(mad_ldflags) \
+       $(faad_ldflags) \
        $(samplerate_ldflags) \
        -lm
 
        $(samplerate_ldflags) \
        -lm
 
@@ -311,6 +314,13 @@ para_recv \
        $(faad_ldflags) \
        $(flac_ldflags)
 
        $(faad_ldflags) \
        $(flac_ldflags)
 
+para_server \
+para_play \
+para_afh \
+para_recv \
+: LDFLAGS += \
+       $(mp4v2_ldflags)
+
 para_server \
 para_client \
 para_audioc \
 para_server \
 para_client \
 para_audioc \
index 3458af959c110a9c21cb81d68287c4a09f3526eb..5b2e9fba0a2b7b50fe25b35e166f66c92973858a 100644 (file)
--- a/aac_afh.c
+++ b/aac_afh.c
 /** \file aac_afh.c para_server's aac audio format handler. */
 
 #include <regex.h>
 /** \file aac_afh.c para_server's aac audio format handler. */
 
 #include <regex.h>
+#include <mp4v2/mp4v2.h>
 
 #include "para.h"
 #include "error.h"
 #include "afh.h"
 #include "string.h"
 #include "aac.h"
 
 #include "para.h"
 #include "error.h"
 #include "afh.h"
 #include "string.h"
 #include "aac.h"
+#include "fd.h"
 
 static int aac_find_stsz(unsigned char *buf, size_t buflen, off_t *skip)
 {
 
 static int aac_find_stsz(unsigned char *buf, size_t buflen, off_t *skip)
 {
@@ -263,6 +265,68 @@ out:
        return ret;
 }
 
        return ret;
 }
 
+static int aac_rewrite_tags(const char *map, size_t mapsize,
+               struct taginfo *tags, int fd, const char *filename)
+{
+       MP4FileHandle h;
+       const MP4Tags *mdata;
+       int ret = write_all(fd, map, mapsize);
+
+       if (ret < 0)
+               return ret;
+       lseek(fd, 0, SEEK_SET);
+       h = MP4Modify(filename, 0);
+       if (!h) {
+               PARA_ERROR_LOG("MP4Modify() failed, fd = %d\n", fd);
+               return -E_MP4V2;
+       }
+       mdata = MP4TagsAlloc();
+       assert(mdata);
+       if (!MP4TagsFetch(mdata, h)) {
+               PARA_ERROR_LOG("MP4Tags_Fetch() failed\n");
+               ret = -E_MP4V2;
+               goto close;
+       }
+
+       if (!MP4TagsSetAlbum(mdata, tags->album)) {
+               PARA_ERROR_LOG("Could not set album\n");
+               ret = -E_MP4V2;
+               goto tags_free;
+       }
+       if (!MP4TagsSetArtist(mdata, tags->artist)) {
+               PARA_ERROR_LOG("Could not set album\n");
+               ret = -E_MP4V2;
+               goto tags_free;
+       }
+       if (!MP4TagsSetComments(mdata, tags->comment)) {
+               PARA_ERROR_LOG("Could not set comment\n");
+               ret = -E_MP4V2;
+               goto tags_free;
+       }
+       if (!MP4TagsSetName(mdata, tags->title)) {
+               PARA_ERROR_LOG("Could not set title\n");
+               ret = -E_MP4V2;
+               goto tags_free;
+       }
+       if (!MP4TagsSetReleaseDate(mdata, tags->year)) {
+               PARA_ERROR_LOG("Could not set release date\n");
+               ret = -E_MP4V2;
+               goto tags_free;
+       }
+
+       if (!MP4TagsStore(mdata, h)) {
+               PARA_ERROR_LOG("Could not store tags\n");
+               ret = -E_MP4V2;
+               goto tags_free;
+       }
+       ret = 1;
+tags_free:
+       MP4TagsFree(mdata);
+close:
+       MP4Close(h, 0);
+       return ret;
+}
+
 static const char* aac_suffixes[] = {"m4a", "mp4", NULL};
 /**
  * the init function of the aac audio format handler
 static const char* aac_suffixes[] = {"m4a", "mp4", NULL};
 /**
  * the init function of the aac audio format handler
@@ -273,4 +337,5 @@ void aac_afh_init(struct audio_format_handler *afh)
 {
        afh->get_file_info = aac_get_file_info,
        afh->suffixes = aac_suffixes;
 {
        afh->get_file_info = aac_get_file_info,
        afh->suffixes = aac_suffixes;
+       afh->rewrite_tags = aac_rewrite_tags;
 }
 }
index 3c031df09162c1b1fa633bcf150cef7f30f5b38e..8b5fb95193b3c15cec63fa64f2c4468a24e76cef 100644 (file)
@@ -412,6 +412,14 @@ AC_CHECK_HEADER(samplerate.h, [], HAVE_SAMPLERATE=no)
 AC_CHECK_LIB([samplerate], [src_process], [], HAVE_SAMPLERATE=no)
 LIB_SUBST_FLAGS(samplerate)
 UNSTASH_FLAGS
 AC_CHECK_LIB([samplerate], [src_process], [], HAVE_SAMPLERATE=no)
 LIB_SUBST_FLAGS(samplerate)
 UNSTASH_FLAGS
+########################################################################## mp4v2
+STASH_FLAGS
+LIB_ARG_WITH([mp4v2], [-lmp4v2])
+HAVE_MP4V2=yes
+AC_CHECK_HEADER([mp4v2/mp4v2.h], [], [HAVE_MP4V2=no])
+AC_CHECK_LIB([mp4v2], [MP4Read], [], [HAVE_MP4V2=no])
+LIB_SUBST_FLAGS(mp4v2)
+UNSTASH_FLAGS
 ######################################################################### server
 if test -n "$CRYPTOLIB" && test $HAVE_OSL = yes; then
        build_server="yes"
 ######################################################################### server
 if test -n "$CRYPTOLIB" && test $HAVE_OSL = yes; then
        build_server="yes"
@@ -466,7 +474,9 @@ if test -n "$CRYPTOLIB" && test $HAVE_OSL = yes; then
        NEED_SPEEX_OBJECTS() && server_errlist_objs="$server_errlist_objs spx_afh spx_common"
        NEED_OPUS_OBJECTS() && server_errlist_objs="$server_errlist_objs opus_afh opus_common"
        NEED_FLAC_OBJECTS && server_errlist_objs="$server_errlist_objs flac_afh"
        NEED_SPEEX_OBJECTS() && server_errlist_objs="$server_errlist_objs spx_afh spx_common"
        NEED_OPUS_OBJECTS() && server_errlist_objs="$server_errlist_objs opus_afh opus_common"
        NEED_FLAC_OBJECTS && server_errlist_objs="$server_errlist_objs flac_afh"
-       test $HAVE_FAAD = yes && server_errlist_objs="$server_errlist_objs aac_afh aac_common"
+       if test $HAVE_FAAD = yes && test $HAVE_MP4V2 = yes; then
+               server_errlist_objs="$server_errlist_objs aac_afh aac_common"
+       fi
        server_objs="add_cmdline($server_cmdline_objs) $server_errlist_objs"
        AC_SUBST(server_objs, add_dot_o($server_objs))
        AC_DEFINE_UNQUOTED(INIT_SERVER_ERRLISTS,
        server_objs="add_cmdline($server_cmdline_objs) $server_errlist_objs"
        AC_SUBST(server_objs, add_dot_o($server_objs))
        AC_DEFINE_UNQUOTED(INIT_SERVER_ERRLISTS,
@@ -823,7 +833,7 @@ NEED_SPEEX_OBJECTS && recv_errlist_objs="$recv_errlist_objs spx_afh spx_common"
 NEED_OPUS_OBJECTS && recv_errlist_objs="$recv_errlist_objs opus_afh opus_common"
 NEED_FLAC_OBJECTS && recv_errlist_objs="$recv_errlist_objs flac_afh"
 
 NEED_OPUS_OBJECTS && recv_errlist_objs="$recv_errlist_objs opus_afh opus_common"
 NEED_FLAC_OBJECTS && recv_errlist_objs="$recv_errlist_objs flac_afh"
 
-if test $HAVE_FAAD = yes; then
+if test $HAVE_FAAD = yes -a $HAVE_MP4V2 = yes; then
        recv_errlist_objs="$recv_errlist_objs aac_afh aac_common"
 fi
 recv_objs="add_cmdline($recv_cmdline_objs) $recv_errlist_objs"
        recv_errlist_objs="$recv_errlist_objs aac_afh aac_common"
 fi
 recv_objs="add_cmdline($recv_cmdline_objs) $recv_errlist_objs"
@@ -863,8 +873,8 @@ NEED_FLAC_OBJECTS && {
        afh_errlist_objs="$afh_errlist_objs flac_afh"
        audio_format_handlers="$audio_format_handlers flac"
 }
        afh_errlist_objs="$afh_errlist_objs flac_afh"
        audio_format_handlers="$audio_format_handlers flac"
 }
-if test $HAVE_FAAD = yes; then
-       afh_errlist_objs="$afh_errlist_objs aac_common aac_afh"
+if test $HAVE_FAAD = yes -a $HAVE_MP4V2 = yes; then
+       afh_errlist_objs="$afh_errlist_objs aac_afh aac_common"
        audio_format_handlers="$audio_format_handlers aac"
 fi
 
        audio_format_handlers="$audio_format_handlers aac"
 fi
 
@@ -939,7 +949,7 @@ NEED_OPUS_OBJECTS &&
 NEED_FLAC_OBJECTS && {
        play_errlist_objs="$play_errlist_objs flacdec_filter flac_afh"
 }
 NEED_FLAC_OBJECTS && {
        play_errlist_objs="$play_errlist_objs flacdec_filter flac_afh"
 }
-if test $HAVE_FAAD = yes; then
+if test $HAVE_FAAD = yes && test $HAVE_MP4V2 = yes; then
        play_errlist_objs="$play_errlist_objs aacdec_filter aac_afh aac_common"
 fi
 if test $HAVE_MAD = yes; then
        play_errlist_objs="$play_errlist_objs aacdec_filter aac_afh aac_common"
 fi
 if test $HAVE_MAD = yes; then
@@ -1133,9 +1143,12 @@ paraslash configuration:
 crypto lib: ${CRYPTOLIB:-[none]}
 unix socket credentials: $have_ucred
 readline (interactive CLIs): $HAVE_READLINE
 crypto lib: ${CRYPTOLIB:-[none]}
 unix socket credentials: $have_ucred
 readline (interactive CLIs): $HAVE_READLINE
-audio formats handlers: $audio_format_handlers
 id3 version 2 support: $HAVE_ID3TAG
 id3 version 2 support: $HAVE_ID3TAG
-filters: $filters
+faad: $HAVE_FAAD
+mp4v2: $HAVE_MP4V2
+
+audio format handlers: $audio_format_handlers
+filters: $(echo $filters)
 writers: $writers
 
 para_fade: $build_fade
 writers: $writers
 
 para_fade: $build_fade
diff --git a/error.h b/error.h
index 90a2fc9e32f2776ae281694a92a87fb0a5a55cdc..122617a9f4209b38d1448dd73e51841aedeb72ac 100644 (file)
--- a/error.h
+++ b/error.h
@@ -417,7 +417,8 @@ extern const char **para_errlist[];
        PARA_ERROR(STSZ, "did not find stcz atom"), \
        PARA_ERROR(MP4ASC, "audio spec config error"), \
        PARA_ERROR(AAC_AFH_INIT, "failed to init aac decoder"), \
        PARA_ERROR(STSZ, "did not find stcz atom"), \
        PARA_ERROR(MP4ASC, "audio spec config error"), \
        PARA_ERROR(AAC_AFH_INIT, "failed to init aac decoder"), \
-
+       PARA_ERROR(MP4V2, "mp4v2 library error"), \
+       PARA_ERROR(NO_AUDIO_TRACK, "file contains no valid audio track"), \
 
 #define AAC_COMMON_ERRORS \
        PARA_ERROR(ESDS, "did not find esds atom"), \
 
 #define AAC_COMMON_ERRORS \
        PARA_ERROR(ESDS, "did not find esds atom"), \
@@ -504,7 +505,6 @@ extern const char **para_errlist[];
        PARA_ERROR(AACDEC_INIT, "failed to init aac decoder"), \
        PARA_ERROR(AAC_DECODE, "aac decode error"), \
 
        PARA_ERROR(AACDEC_INIT, "failed to init aac decoder"), \
        PARA_ERROR(AAC_DECODE, "aac decode error"), \
 
-
 #define CHUNK_QUEUE_ERRORS \
        PARA_ERROR(QUEUE, "packet queue overrun"), \
 
 #define CHUNK_QUEUE_ERRORS \
        PARA_ERROR(QUEUE, "packet queue overrun"), \