shithub: aacdec

Download patch

ref: b5330cb64af703185462b3a28eb0d1ee16f36789
parent: b9ec5d0956e8f128a0afa2bf200fe577de7084fb
author: menno <menno>
date: Fri Sep 3 15:38:58 EDT 2004

New winamp plugin:
Now uses mp4ff library instead of mp4v2 from mpeg4ip.

--- a/common/mp4ff/mp4ff.h
+++ b/common/mp4ff/mp4ff.h
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: mp4ff.h,v 1.20 2004/03/27 11:14:49 menno Exp $
+** $Id: mp4ff.h,v 1.21 2004/09/03 19:38:58 menno Exp $
 **/
 
 #ifndef MP4FF_H
@@ -98,6 +98,8 @@
 int mp4ff_meta_get_genre(const mp4ff_t *f, char **value);
 int mp4ff_meta_get_track(const mp4ff_t *f, char **value);
 int mp4ff_meta_get_disc(const mp4ff_t *f, char **value);
+int mp4ff_meta_get_totaltracks(const mp4ff_t *f, char **value);
+int mp4ff_meta_get_totaldiscs(const mp4ff_t *f, char **value);
 int mp4ff_meta_get_compilation(const mp4ff_t *f, char **value);
 int mp4ff_meta_get_tempo(const mp4ff_t *f, char **value);
 int32_t mp4ff_meta_get_coverart(const mp4ff_t *f, char **value);
--- a/common/mp4ff/mp4meta.c
+++ b/common/mp4ff/mp4meta.c
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: mp4meta.c,v 1.14 2004/03/27 11:14:49 menno Exp $
+** $Id: mp4meta.c,v 1.15 2004/09/03 19:38:58 menno Exp $
 **/
 
 #ifdef USE_TAGGING
@@ -393,9 +393,19 @@
     return mp4ff_meta_find_by_name(f, "track", value);
 }
 
+int32_t mp4ff_meta_get_totaltracks(const mp4ff_t *f, char **value)
+{
+    return mp4ff_meta_find_by_name(f, "totaltracks", value);
+}
+
 int32_t mp4ff_meta_get_disc(const mp4ff_t *f, char **value)
 {
     return mp4ff_meta_find_by_name(f, "disc", value);
+}
+
+int32_t mp4ff_meta_get_totaldiscs(const mp4ff_t *f, char **value)
+{
+    return mp4ff_meta_find_by_name(f, "totaldiscs", value);
 }
 
 int32_t mp4ff_meta_get_compilation(const mp4ff_t *f, char **value)
--- a/plugins/in_mp4/in_mp4.c
+++ b/plugins/in_mp4/in_mp4.c
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: in_mp4.c,v 1.51 2004/03/04 19:06:01 menno Exp $
+** $Id: in_mp4.c,v 1.52 2004/09/03 19:38:32 menno Exp $
 **/
 
 //#define DEBUG_OUTPUT
@@ -32,9 +32,12 @@
 #include <commctrl.h>
 #include <commdlg.h>
 #include <stdlib.h>
+#include <stdio.h>
+#include <io.h>
 #include <math.h>
 #include <neaacdec.h>
-#include <mp4.h>
+#define USE_TAGGING
+#include <mp4ff.h>
 
 #include "resource.h"
 #include "in2.h"
@@ -41,7 +44,6 @@
 #include "utils.h"
 #include "config.h"
 #include "aacinfo.h"
-#include "aac2mp4.h"
 
 const char *long_ext_list = "MP4\0MPEG-4 Files (*.MP4)\0M4A\0MPEG-4 Files (*.M4A)\0AAC\0AAC Files (*.AAC)\0";
 const char *short_ext_list = "MP4\0MPEG-4 Files (*.MP4)\0M4A\0MPEG-4 Files (*.M4A)\0";
@@ -96,10 +98,12 @@
     __int64 last_offset;
 
     /* MP4 stuff */
-    MP4FileHandle mp4file;
+    mp4ff_t *mp4file;
     int mp4track;
-    MP4SampleId numSamples;
-    MP4SampleId sampleId;
+    long numSamples;
+    long sampleId;
+    mp4ff_callback_t mp4cb;
+    FILE *mp4File;
 
     /* AAC stuff */
     FILE *aacfile;
@@ -135,26 +139,35 @@
 DWORD WINAPI AACPlayThread(void *b); // the decode thread procedure
 
 
-typedef struct tag
+uint32_t read_callback(void *user_data, void *buffer, uint32_t length)
 {
-    char *item;
-    char *value;
-    size_t len;
-} tag;
+    return fread(buffer, 1, length, (FILE*)user_data);
+}
 
-typedef struct medialib_tags
+uint32_t seek_callback(void *user_data, uint64_t position)
 {
-    struct tag *tags;
-    unsigned int count;
-} medialib_tags;
+    return fseek((FILE*)user_data, position, SEEK_SET);
+}
 
-int tag_add_field(medialib_tags *tags, const char *item, const char *value, size_t v_len)
+uint32_t write_callback(void *user_data, void *buffer, uint32_t length)
 {
+    return fwrite(buffer, 1, length, (FILE*)user_data);
+}
+
+uint32_t truncate_callback(void *user_data)
+{
+    _chsize(fileno((FILE*)user_data), ftell((FILE*)user_data));
+    return 1;
+}
+
+
+int tag_add_field(mp4ff_metadata_t *tags, const char *item, const char *value, size_t v_len)
+{
     void *backup = (void *)tags->tags;
 
     if (!item || (item && !*item) || !value) return 0;
 
-    tags->tags = (struct tag *)realloc(tags->tags, (tags->count+1) * sizeof(tag));
+    tags->tags = (mp4ff_tag_t *)realloc(tags->tags, (tags->count+1) * sizeof(mp4ff_tag_t));
     if (!tags->tags) {
         if (backup) free(backup);
         return 0;
@@ -180,7 +193,7 @@
         memcpy(tags->tags[tags->count].value, value, v_len);
         tags->tags[tags->count].item[i_len] = '\0';
         tags->tags[tags->count].value[v_len] = '\0';
-        tags->tags[tags->count].len = v_len;
+//        tags->tags[tags->count].len = v_len;
 
         tags->count++;
         return 1;
@@ -187,7 +200,7 @@
     }
 }
 
-int tag_set_field(medialib_tags *tags, const char *item, const char *value, size_t v_len)
+int tag_set_field(mp4ff_metadata_t *tags, const char *item, const char *value, size_t v_len)
 {
     unsigned int i;
 
@@ -209,7 +222,7 @@
 
             memcpy(tags->tags[i].value, value, v_len);
             tags->tags[i].value[v_len] = '\0';
-            tags->tags[i].len = v_len;
+//            tags->tags[i].len = v_len;
 
             return 1;
         }
@@ -218,7 +231,7 @@
     return tag_add_field(tags, item, value, v_len);
 }
 
-int tag_delete(medialib_tags *tags)
+int tag_delete(mp4ff_metadata_t *tags)
 {
     unsigned int i;
 
@@ -234,9 +247,8 @@
     tags->count = 0;
 }
 
-int ReadMP4Tag(MP4FileHandle file, medialib_tags *tags)
+int ReadMP4Tag(mp4ff_t *file, mp4ff_metadata_t *tags)
 {
-    unsigned __int32 valueSize;
     unsigned __int8 *pValue;
     char *pName;
     unsigned int i = 0;
@@ -244,89 +256,51 @@
     do {
         pName = 0;
         pValue = 0;
-        valueSize = 0;
 
-        MP4GetMetadataByIndex(file, i, (const char **)&pName, &pValue, &valueSize);
 
-        if (valueSize > 0)
+        if (mp4ff_meta_get_by_index(file, i, (char **)&pName, &pValue))
         {
-            char *val = (char *)malloc(valueSize+1);
+            char *val = (char *)strdup(pValue);
             if (!val) return 0;
-            memcpy(val, pValue, valueSize);
-            val[valueSize] = '\0';
 
             if (pName[0] == '�')
             {
                 if (memcmp(pName, "�nam", 4) == 0)
                 {
-                    tag_add_field(tags, "title", val, valueSize);
+                    tag_add_field(tags, "title", val, strlen(val));
                 } else if (memcmp(pName, "�ART", 4) == 0) {
-                    tag_add_field(tags, "artist", val, valueSize);
+                    tag_add_field(tags, "artist", val, strlen(val));
                 } else if (memcmp(pName, "�wrt", 4) == 0) {
-                    tag_add_field(tags, "writer", val, valueSize);
+                    tag_add_field(tags, "writer", val, strlen(val));
                 } else if (memcmp(pName, "�alb", 4) == 0) {
-                    tag_add_field(tags, "album", val, valueSize);
+                    tag_add_field(tags, "album", val, strlen(val));
                 } else if (memcmp(pName, "�day", 4) == 0) {
-                    tag_add_field(tags, "date", val, valueSize);
+                    tag_add_field(tags, "date", val, strlen(val));
                 } else if (memcmp(pName, "�too", 4) == 0) {
-                    tag_add_field(tags, "tool", val, valueSize);
+                    tag_add_field(tags, "tool", val, strlen(val));
                 } else if (memcmp(pName, "�cmt", 4) == 0) {
-                    tag_add_field(tags, "comment", val, valueSize);
+                    tag_add_field(tags, "comment", val, strlen(val));
                 } else if (memcmp(pName, "�gen", 4) == 0) {
-                    tag_add_field(tags, "genre", val, valueSize);
+                    tag_add_field(tags, "genre", val, strlen(val));
                 } else {
-                    tag_add_field(tags, pName, val, valueSize);
+                    tag_add_field(tags, pName, val, strlen(val));
                 }
             } else if (memcmp(pName, "covr", 4) == 0) {
-                tag_add_field(tags, "cover", val, valueSize);
+                tag_add_field(tags, "cover", val, strlen(val));
             } else if (memcmp(pName, "gnre", 4) == 0) {
-                char *t=0;
-                if (MP4GetMetadataGenre(file, &t))
-                {
-                    tag_add_field(tags, "genre", t, 0);
-                }
+                tag_add_field(tags, "genre", val, strlen(val));
             } else if (memcmp(pName, "trkn", 4) == 0) {
-                unsigned __int16 trkn = 0, tot = 0;
-                char t[200];
-                if (MP4GetMetadataTrack(file, &trkn, &tot))
-                {
-                    if (tot > 0)
-                        wsprintf(t, "%d/%d", trkn, tot);
-                    else
-                        wsprintf(t, "%d", trkn);
-                    tag_add_field(tags, "tracknumber", t, 0);
-                }
+                tag_add_field(tags, "tracknumber", val, strlen(val));
             } else if (memcmp(pName, "disk", 4) == 0) {
-                unsigned __int16 disk = 0, tot = 0;
-                char t[200];
-                if (MP4GetMetadataDisk(file, &disk, &tot))
-                {
-                    if (tot > 0)
-                        wsprintf(t, "%d/%d", disk, tot);
-                    else
-                        wsprintf(t, "%d", disk);
-                    tag_add_field(tags, "disc", t, 0);
-                }
+                tag_add_field(tags, "disc", val, strlen(val));
             } else if (memcmp(pName, "cpil", 4) == 0) {
-                unsigned __int8 cpil = 0;
-                char t[200];
-                if (MP4GetMetadataCompilation(file, &cpil))
-                {
-                    wsprintf(t, "%d", cpil);
-                    tag_add_field(tags, "compilation", t, 0);
-                }
+                tag_add_field(tags, "compilation", val, strlen(val));
             } else if (memcmp(pName, "tmpo", 4) == 0) {
-                unsigned __int16 tempo = 0;
-                char t[200];
-                if (MP4GetMetadataTempo(file, &tempo))
-                {
-                    wsprintf(t, "%d BPM", tempo);
-                    tag_add_field(tags, "tempo", t, 0);
-                }
+                tag_add_field(tags, "tempo", val, strlen(val));
             } else if (memcmp(pName, "NDFL", 4) == 0) {
                 /* Removed */
             } else {
-                tag_add_field(tags, pName, val, valueSize);
+                tag_add_field(tags, pName, val, strlen(val));
             }
 
             free(val);
@@ -333,107 +307,12 @@
         }
 
         i++;
-    } while (valueSize > 0);
+    } while (pValue != NULL);
 
     return 1;
 }
 
-int mp4_set_metadata(MP4FileHandle file, const char *item, const char *val, size_t v_len)
-{
-    if (!item || (item && !*item) || !val) return 0;
 
-    if (!stricmp(item, "track") || !stricmp(item, "tracknumber"))
-    {
-        unsigned __int16 trkn, tot;
-        int t1 = 0, t2 = 0;
-        sscanf(val, "%d/%d", &t1, &t2);
-        trkn = t1, tot = t2;
-        if (!trkn) return 1;
-        if (MP4SetMetadataTrack(file, trkn, tot)) return 1;
-    }
-    else if (!stricmp(item, "disc") || !stricmp(item, "disknumber"))
-    {
-        unsigned __int16 disk, tot;
-        int t1 = 0, t2 = 0;
-        sscanf(val, "%d/%d", &t1, &t2);
-        disk = t1, tot = t2;
-        if (!disk) return 1;
-        if (MP4SetMetadataDisk(file, disk, tot)) return 1;
-    }
-    else if (!stricmp(item, "compilation"))
-    {
-        unsigned __int8 cpil = atoi(val);
-        if (!cpil) return 1;
-        if (MP4SetMetadataCompilation(file, cpil)) return 1;
-    }
-    else if (!stricmp(item, "tempo"))
-    {
-        unsigned __int16 tempo = atoi(val);
-        if (!tempo) return 1;
-        if (MP4SetMetadataTempo(file, tempo)) return 1;
-    }
-    else if (!stricmp(item, "artist"))
-    {
-        if (MP4SetMetadataArtist(file, val)) return 1;
-    }
-    else if (!stricmp(item, "writer"))
-    {
-        if (MP4SetMetadataWriter(file, val)) return 1;
-    }
-    else if (!stricmp(item, "title"))
-    {
-        if (MP4SetMetadataName(file, val)) return 1;
-    }
-    else if (!stricmp(item, "album"))
-    {
-        if (MP4SetMetadataAlbum(file, val)) return 1;
-    }
-    else if (!stricmp(item, "date") || !stricmp(item, "year"))
-    {
-        if (MP4SetMetadataYear(file, val)) return 1;
-    }
-    else if (!stricmp(item, "comment"))
-    {
-        if (MP4SetMetadataComment(file, val)) return 1;
-    }
-    else if (!stricmp(item, "genre"))
-    {
-        if (MP4SetMetadataGenre(file, val)) return 1;
-    }
-    else if (!stricmp(item, "tool"))
-    {
-        if (MP4SetMetadataTool(file, val)) return 1;
-    }
-    else if (!stricmp(item, "cover"))
-    {
-        if (MP4SetMetadataCoverArt(file, val, v_len)) return 1;
-    }
-    else
-    {
-        if (MP4SetMetadataFreeForm(file, (char *)item, (u_int8_t *)val, (u_int32_t)v_len)) return 1;
-    }
-
-    return 0;
-}
-
-int WriteMP4Tag(MP4FileHandle file, const medialib_tags *tags)
-{
-    unsigned int i;
-
-    for (i = 0; i < tags->count; i++)
-    {
-        const char *item = tags->tags[i].item;
-        const char *value = tags->tags[i].value;
-        size_t len = tags->tags[i].len;
-
-        if (value && len > 0)
-        {
-            mp4_set_metadata(file, item, value, len);
-        }
-    }
-}
-
-
 #ifdef DEBUG_OUTPUT
 void in_mp4_DebugOutput(char *message)
 {
@@ -756,15 +635,55 @@
     return len;
 }
 
+static void mp4fileinfo(mp4ff_t *mp4, char *info, size_t len)
+{
+    char *ot[6] = { "NULL", "MAIN AAC", "LC AAC", "SSR AAC", "LTP AAC", "HE AAC" };
+    long samples;
+    float f = 1024.0;
+    float seconds;
+    int track;
+
+    mp4AudioSpecificConfig mp4ASC = {0};
+    unsigned char *buffer = NULL;
+    int buffer_size = 0;
+
+    if ((track = GetAACTrack(mp4)) < 0)
+    {
+        info[0] = '\0';
+        return;
+    }
+
+    samples = mp4ff_num_samples(mp4, track);
+
+    mp4ff_get_decoder_config(mp4, track, &buffer, &buffer_size);
+    if (buffer)
+    {
+        if (NeAACDecAudioSpecificConfig(buffer, buffer_size, &mp4ASC) >= 0)
+        {
+            if (mp4ASC.frameLengthFlag == 1) f = 960.0;
+            if (mp4ASC.sbr_present_flag == 1) f *= 2;
+        }
+        free(buffer);
+    }
+
+    seconds = (float)samples*(float)(f-1.0)/(float)mp4ASC.samplingFrequency;
+
+    wsprintf(info, "%s\t%d.%d secs, %d ch, %d Hz\n\n", ot[(mp4ASC.objectTypeIndex > 5)?0:mp4ASC.objectTypeIndex],
+        (int)(seconds), (int)(seconds*1000.0 + 0.5) % 1000, mp4ASC.channelsConfiguration, mp4ASC.samplingFrequency);
+}
+
 BOOL CALLBACK mp4_info_dialog_proc(HWND hwndDlg, UINT message,
                                    WPARAM wParam, LPARAM lParam)
 {
-    char *file_info;
-    MP4FileHandle file;
-    char *pVal, dummy1[1024], dummy3;
-    short dummy, dummy2;
+    char file_info[1024];
+    mp4ff_t *file;
+    FILE *mp4File;
+    mp4ff_callback_t mp4cb = {0};
+    char *pVal;
+    mp4ff_metadata_t tags;
+    char dummy1[1024];
     char temp[1024];
-    struct medialib_tags tags;
+    int dummy, dummy2, dummy3;
     tags.count = 0;
     tags.tags = NULL;
 
@@ -781,87 +700,85 @@
         EnableWindow(GetDlgItem(hwndDlg,IDC_CONVERT2), FALSE);
         ShowWindow(GetDlgItem(hwndDlg,IDC_CONVERT2), SW_HIDE);
 
-        file = MP4Read(info_fn, 0);
+        mp4File = fopen(info_fn, "rb");
+        mp4cb.read = read_callback;
+        mp4cb.seek = seek_callback;
+        mp4cb.user_data = mp4File;
 
-        if (file == MP4_INVALID_FILE_HANDLE)
+
+        file = mp4ff_open_read(&mp4cb);
+        if (file == NULL)
             return FALSE;
 
-        file_info = MP4Info(file, MP4_INVALID_TRACK_ID);
+        mp4fileinfo(file, file_info, 1024);
         SetDlgItemText(hwndDlg, IDC_INFOTEXT, file_info);
-        free(file_info);
 
         /* get Metadata */
 
         pVal = NULL;
-        if (MP4GetMetadataName(file, &pVal))
+        if (mp4ff_meta_get_title(file, &pVal))
             uSetDlgItemText(hwndDlg,IDC_METANAME, pVal);
 
         pVal = NULL;
-        if (MP4GetMetadataArtist(file, &pVal))
+        if (mp4ff_meta_get_artist(file, &pVal))
             uSetDlgItemText(hwndDlg,IDC_METAARTIST, pVal);
 
         pVal = NULL;
-        if (MP4GetMetadataWriter(file, &pVal))
+        if (mp4ff_meta_get_writer(file, &pVal))
             uSetDlgItemText(hwndDlg,IDC_METAWRITER, pVal);
 
         pVal = NULL;
-        if (MP4GetMetadataComment(file, &pVal))
+        if (mp4ff_meta_get_comment(file, &pVal))
             uSetDlgItemText(hwndDlg,IDC_METACOMMENTS, pVal);
 
         pVal = NULL;
-        if (MP4GetMetadataAlbum(file, &pVal))
+        if (mp4ff_meta_get_album(file, &pVal))
             uSetDlgItemText(hwndDlg,IDC_METAALBUM, pVal);
 
         pVal = NULL;
-        if (MP4GetMetadataGenre(file, &pVal))
+        if (mp4ff_meta_get_genre(file, &pVal))
             uSetDlgItemText(hwndDlg,IDC_METAGENRE, pVal);
 
-        dummy = 0;
-        MP4GetMetadataTempo(file, &dummy);
-        if (dummy)
+        pVal = NULL;
+        if (mp4ff_meta_get_track(file, &pVal))
         {
-            wsprintf(dummy1, "%d", dummy);
-            SetDlgItemText(hwndDlg,IDC_METATEMPO, dummy1);
-        }
+            SetDlgItemText(hwndDlg,IDC_METATRACK1, pVal);
 
-        dummy = 0; dummy2 = 0;
-        MP4GetMetadataTrack(file, &dummy, &dummy2);
-        if (dummy)
-        {
-            wsprintf(dummy1, "%d", dummy);
-            SetDlgItemText(hwndDlg,IDC_METATRACK1, dummy1);
+            //pVal = NULL;
+            //mp4ff_meta_get_totaltracks(file, &pVal);
+            //SetDlgItemText(hwndDlg, IDC_METATRACK2, pVal);
         }
-        if (dummy2)
-        {
-            wsprintf(dummy1, "%d", dummy2);
-            SetDlgItemText(hwndDlg,IDC_METATRACK2, dummy1);
-        }
 
-        dummy = 0; dummy2 = 0;
-        MP4GetMetadataDisk(file, &dummy, &dummy2);
-        if (dummy)
+        pVal = NULL;
+        if (mp4ff_meta_get_disc(file, &pVal))
         {
-            wsprintf(dummy1, "%d", dummy);
-            SetDlgItemText(hwndDlg,IDC_METADISK1, dummy1);
+            SetDlgItemText(hwndDlg,IDC_METADISK1, pVal);
+
+            //pVal = NULL;
+            //mp4ff_meta_get_totaldiscs(file, &pVal);
+            //SetDlgItemText(hwndDlg,IDC_METADISK2, pVal);
         }
-        if (dummy2)
-        {
-            wsprintf(dummy1, "%d", dummy2);
-            SetDlgItemText(hwndDlg,IDC_METADISK2, dummy1);
-        }
 
         pVal = NULL;
-        if (MP4GetMetadataYear(file, &pVal))
+        if (mp4ff_meta_get_date(file, &pVal))
             uSetDlgItemText(hwndDlg,IDC_METAYEAR, pVal);
 
-        dummy3 = 0;
-        MP4GetMetadataCompilation(file, &dummy3);
-        if (dummy3)
-            SendMessage(GetDlgItem(hwndDlg, IDC_METACOMPILATION), BM_SETCHECK, BST_CHECKED, 0);
+#if 0
+        /* WERKT NIET */
+#endif
+        pVal = NULL;
+        if (mp4ff_meta_get_compilation(file, &pVal))
+        {
+            if (strcmp(pVal, "1") == 0)
+            {
+                SendMessage(GetDlgItem(hwndDlg, IDC_METACOMPILATION), BM_SETCHECK, BST_CHECKED, 0);
+            }
+        }
 
         /* ! Metadata */
 
-        MP4Close(file);
+        mp4ff_close(file);
+        fclose(mp4File);
 
         return TRUE;
 
@@ -883,74 +800,75 @@
             /* save Metadata changes */
 
             tag_delete(&tags);
-            file = MP4Read(info_fn, 0);
-            if (file != MP4_INVALID_FILE_HANDLE)
-            {
-                ReadMP4Tag(file, &tags);
-                MP4Close(file);
 
-                file = MP4Modify(info_fn, 0, 0);
-                if (file != MP4_INVALID_FILE_HANDLE)
-                {
-                    MP4MetadataDelete(file);
-                    MP4Close(file);
-                }
-            }
+            mp4File = fopen(info_fn, "rb");
+            mp4cb.read = read_callback;
+            mp4cb.seek = seek_callback;
+            mp4cb.write = write_callback;
+            mp4cb.truncate = truncate_callback;
+            mp4cb.user_data = mp4File;
 
-            file = MP4Modify(info_fn, 0, 0);
-            if (file == MP4_INVALID_FILE_HANDLE)
+
+            file = mp4ff_open_read(&mp4cb);
+            if (file != NULL)
             {
-                tag_delete(&tags);
-                EndDialog(hwndDlg, wParam);
-                return FALSE;
+                ReadMP4Tag(file, &tags);
+                mp4ff_close(file);
+                fclose(mp4File);
             }
 
+            mp4File = fopen(info_fn, "rb+");
+            mp4cb.read = read_callback;
+            mp4cb.seek = seek_callback;
+            mp4cb.write = write_callback;
+            mp4cb.truncate = truncate_callback;
+            mp4cb.user_data = mp4File;
+
+
             uGetDlgItemText(hwndDlg, IDC_METANAME, dummy1, 1024);
-            tag_set_field(&tags, "title", dummy1, 0);
+            tag_set_field(&tags, "title", dummy1, strlen(dummy1));
 
             uGetDlgItemText(hwndDlg, IDC_METAWRITER, dummy1, 1024);
-            tag_set_field(&tags, "writer", dummy1, 0);
+            tag_set_field(&tags, "writer", dummy1, strlen(dummy1));
 
             uGetDlgItemText(hwndDlg, IDC_METAARTIST, dummy1, 1024);
-            tag_set_field(&tags, "artist", dummy1, 0);
+            tag_set_field(&tags, "artist", dummy1, strlen(dummy1));
 
             uGetDlgItemText(hwndDlg, IDC_METAALBUM, dummy1, 1024);
-            tag_set_field(&tags, "album", dummy1, 0);
+            tag_set_field(&tags, "album", dummy1, strlen(dummy1));
 
             uGetDlgItemText(hwndDlg, IDC_METACOMMENTS, dummy1, 1024);
-            tag_set_field(&tags, "comment", dummy1, 0);
+            tag_set_field(&tags, "comment", dummy1, strlen(dummy1));
 
             uGetDlgItemText(hwndDlg, IDC_METAGENRE, dummy1, 1024);
-            tag_set_field(&tags, "genre", dummy1, 0);
+            tag_set_field(&tags, "genre", dummy1, strlen(dummy1));
 
             uGetDlgItemText(hwndDlg, IDC_METAYEAR, dummy1, 1024);
-            tag_set_field(&tags, "year", dummy1, 0);
+            tag_set_field(&tags, "year", dummy1, strlen(dummy1));
 
             GetDlgItemText(hwndDlg, IDC_METATRACK1, dummy1, 1024);
             dummy = atoi(dummy1);
-            GetDlgItemText(hwndDlg, IDC_METATRACK2, dummy1, 1024);
-            dummy2 = atoi(dummy1);
-            wsprintf(temp, "%d/%d", dummy, dummy2);
-            tag_set_field(&tags, "track", temp, 0);
+            //GetDlgItemText(hwndDlg, IDC_METATRACK2, dummy1, 1024);
+            //dummy2 = atoi(dummy1);
+            //wsprintf(temp, "%d/%d", dummy, dummy2);
+            wsprintf(temp, "%d", dummy);
+            tag_set_field(&tags, "track", temp, strlen(dummy1));
 
             GetDlgItemText(hwndDlg, IDC_METADISK1, dummy1, 1024);
             dummy = atoi(dummy1);
-            GetDlgItemText(hwndDlg, IDC_METADISK2, dummy1, 1024);
-            dummy2 = atoi(dummy1);
-            wsprintf(temp, "%d/%d", dummy, dummy2);
-            tag_set_field(&tags, "disc", temp, 0);
+            //GetDlgItemText(hwndDlg, IDC_METADISK2, dummy1, 1024);
+            //dummy2 = atoi(dummy1);
+            //wsprintf(temp, "%d/%d", dummy, dummy2);
+            wsprintf(temp, "%d", dummy);
+            tag_set_field(&tags, "disc", temp, strlen(dummy1));
 
-            GetDlgItemText(hwndDlg, IDC_METATEMPO, dummy1, 1024);
-            tag_set_field(&tags, "tempo", dummy1, 0);
-
             dummy3 = SendMessage(GetDlgItem(hwndDlg, IDC_METACOMPILATION), BM_GETCHECK, 0, 0);
-            tag_set_field(&tags, "compilation", (dummy3 ? "1" : "0"), 0);
+            tag_set_field(&tags, "compilation", (dummy3 ? "1" : "0"), 1);
 
-            WriteMP4Tag(file, &tags);
+            mp4ff_meta_update(&mp4cb, &tags);
 
-            MP4Close(file);
+            fclose(mp4File);
 
-            MP4Optimize(info_fn, NULL, 0);
             /* ! */
 
             EndDialog(hwndDlg, wParam);
@@ -1011,11 +929,10 @@
         ShowWindow(GetDlgItem(hwndDlg,IDC_METACOMMENTS), SW_HIDE);
         ShowWindow(GetDlgItem(hwndDlg,IDC_METAALBUM), SW_HIDE);
         ShowWindow(GetDlgItem(hwndDlg,IDC_METAGENRE), SW_HIDE);
-        ShowWindow(GetDlgItem(hwndDlg,IDC_METATEMPO), SW_HIDE);
         ShowWindow(GetDlgItem(hwndDlg,IDC_METATRACK1), SW_HIDE);
-        ShowWindow(GetDlgItem(hwndDlg,IDC_METATRACK2), SW_HIDE);
+        //ShowWindow(GetDlgItem(hwndDlg,IDC_METATRACK2), SW_HIDE);
         ShowWindow(GetDlgItem(hwndDlg,IDC_METADISK1), SW_HIDE);
-        ShowWindow(GetDlgItem(hwndDlg,IDC_METADISK2), SW_HIDE);
+        //ShowWindow(GetDlgItem(hwndDlg,IDC_METADISK2), SW_HIDE);
         ShowWindow(GetDlgItem(hwndDlg,IDC_METAYEAR), SW_HIDE);
         ShowWindow(GetDlgItem(hwndDlg,IDC_METACOMPILATION), SW_HIDE);
 
@@ -1051,38 +968,6 @@
     case WM_COMMAND:
         switch (LOWORD(wParam))
         {
-        case IDC_CONVERT:
-            {
-                char mp4FileName[256];
-                char *extension;
-                OPENFILENAME ofn;
-
-                lstrcpy(mp4FileName, info_fn);
-                extension = strrchr(mp4FileName, '.');
-                lstrcpy(extension, ".mp4");
-
-                memset(&ofn, 0, sizeof(OPENFILENAME));
-                ofn.lStructSize = sizeof(OPENFILENAME);
-                ofn.hwndOwner = hwndDlg;
-                ofn.hInstance = module.hDllInstance;
-                ofn.nMaxFileTitle = 31;
-                ofn.lpstrFile = (LPSTR)mp4FileName;
-                ofn.nMaxFile = _MAX_PATH;
-                ofn.lpstrFilter = "MP4 Files (*.mp4)\0*.mp4\0";
-                ofn.lpstrDefExt = "mp4";
-                ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
-                ofn.lpstrTitle = "Select Output File";
-
-                if (GetSaveFileName(&ofn))
-                {
-                    if (covert_aac_to_mp4(info_fn, mp4FileName))
-                    {
-                        MessageBox(hwndDlg, "An error occured while converting AAC to MP4!", "An error occured!", MB_OK);
-                        return FALSE;
-                    }
-                }
-                return TRUE;
-            }
         case IDCANCEL:
         case IDOK:
             EndDialog(hwndDlg, wParam);
@@ -1111,7 +996,7 @@
 }
 
 /* Get the title from the file */
-void ConstructTitle(MP4FileHandle file, char *filename, char *title, char *format)
+void ConstructTitle(mp4ff_t *file, char *filename, char *title, char *format)
 {
     char temp[4096];
     int some_info = 0;
@@ -1138,10 +1023,10 @@
         switch (*in++)
         {
         case '0':
-            dummy = 0; dummy2 = 0;
-            if (MP4GetMetadataTrack(file, &dummy, &dummy2))
+            pVal = NULL;
+            if (mp4ff_meta_get_track(file, &pVal))
             {
-                out += wsprintf(out, "%d", (int)dummy);
+                out += wsprintf(out, "%s", pVal);
                 some_info = 1;
             }
             break;
@@ -1148,7 +1033,7 @@
 
         case '1':
             pVal = NULL;
-            if (MP4GetMetadataArtist(file, &pVal))
+            if (mp4ff_meta_get_artist(file, &pVal))
             {
                 out += wsprintf(out, "%s", pVal);
                 some_info = 1;
@@ -1157,7 +1042,7 @@
 
         case '2':
             pVal = NULL;
-            if (MP4GetMetadataName(file, &pVal))
+            if (mp4ff_meta_get_title(file, &pVal))
             {
                 out += wsprintf(out, "%s", pVal);
                 some_info = 1;
@@ -1166,7 +1051,7 @@
 
         case '3':
             pVal = NULL;
-            if (MP4GetMetadataAlbum(file, &pVal))
+            if (mp4ff_meta_get_album(file, &pVal))
             {
                 out += wsprintf(out, "%s", pVal);
                 some_info = 1;
@@ -1175,7 +1060,7 @@
 
         case '4':
             pVal = NULL;
-            if (MP4GetMetadataYear(file, &pVal))
+            if (mp4ff_meta_get_date(file, &pVal))
             {
                 out += wsprintf(out, "%s", pVal);
                 some_info = 1;
@@ -1184,7 +1069,7 @@
 
         case '5':
             pVal = NULL;
-            if (MP4GetMetadataComment(file, &pVal))
+            if (mp4ff_meta_get_comment(file, &pVal))
             {
                 out += wsprintf(out, "%s", pVal);
                 some_info = 1;
@@ -1193,7 +1078,7 @@
 
         case '6':
             pVal = NULL;
-            if (MP4GetMetadataGenre(file, &pVal))
+            if (mp4ff_meta_get_genre(file, &pVal))
             {
                 out += wsprintf(out, "%s", pVal);
                 some_info = 1;
@@ -1461,6 +1346,8 @@
     unsigned char *buffer;
     int buffer_size;
     NeAACDecConfigurationPtr config;
+    unsigned char header[8];
+    FILE *hMP4File;
 
 #ifdef DEBUG_OUTPUT
     in_mp4_DebugOutput("play");
@@ -1470,13 +1357,16 @@
 
     lstrcpy(mp4state.filename, fn);
 
-    if (!(mp4state.mp4file = MP4Read(mp4state.filename, 0)))
+    hMP4File = fopen(mp4state.filename, "rb");
+    if (!hMP4File)
     {
-        mp4state.filetype = 1;
-    } else {
-        MP4Close(mp4state.mp4file);
-        mp4state.filetype = 0;
+        return -1;
     }
+    fread(header, 1, 8, hMP4File);
+    fclose(hMP4File);
+    mp4state.filetype = 1;
+    if (header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p')
+        mp4state.filetype = 0;
 
     if (mp4state.filetype)
     {
@@ -1640,7 +1530,13 @@
         config->downMatrix = m_downmix;
         NeAACDecSetConfiguration(mp4state.hDecoder, config);
 
-        mp4state.mp4file = MP4Read(mp4state.filename, 0);
+        mp4state.mp4File = fopen(mp4state.filename, "rb");
+        mp4state.mp4cb.read = read_callback;
+        mp4state.mp4cb.seek = seek_callback;
+        mp4state.mp4cb.user_data = mp4state.mp4File;
+
+
+        mp4state.mp4file = mp4ff_open_read(&mp4state.mp4cb);
         if (!mp4state.mp4file)
         {
             show_error(module.hMainWindow, "Unable to open file.");
@@ -1652,18 +1548,20 @@
         {
             show_error(module.hMainWindow, "Unsupported Audio track type.");
             NeAACDecClose(mp4state.hDecoder);
-            MP4Close(mp4state.mp4file);
+            mp4ff_close(mp4state.mp4file);
+            fclose(mp4state.mp4File);
             return -1;
         }
 
         buffer = NULL;
         buffer_size = 0;
-        MP4GetTrackESConfiguration(mp4state.mp4file, mp4state.mp4track,
+        mp4ff_get_decoder_config(mp4state.mp4file, mp4state.mp4track,
             &buffer, &buffer_size);
         if (!buffer)
         {
             NeAACDecClose(mp4state.hDecoder);
-            MP4Close(mp4state.mp4file);
+            mp4ff_close(mp4state.mp4file);
+            fclose(mp4state.mp4File);
             return -1;
         }
 
@@ -1672,7 +1570,8 @@
         {
             /* If some error initializing occured, skip the file */
             NeAACDecClose(mp4state.hDecoder);
-            MP4Close(mp4state.mp4file);
+            mp4ff_close(mp4state.mp4file);
+            fclose(mp4state.mp4File);
             if (buffer) free (buffer);
             return -1;
         }
@@ -1681,7 +1580,7 @@
         {
             mp4AudioSpecificConfig mp4ASC;
 
-            mp4state.timescale = MP4GetTrackTimeScale(mp4state.mp4file, mp4state.mp4track);
+            mp4state.timescale = mp4ff_time_scale(mp4state.mp4file, mp4state.mp4track);
             mp4state.framesize = 1024;
             mp4state.useAacLength = 0;
 
@@ -1697,11 +1596,10 @@
 
         free(buffer);
 
-        avg_bitrate = MP4GetTrackIntegerProperty(mp4state.mp4file, mp4state.mp4track,
-            "mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.avgBitrate");
+        avg_bitrate = mp4ff_get_avg_bitrate(mp4state.mp4file, mp4state.mp4track);
 
-        mp4state.numSamples = MP4GetTrackNumberOfSamples(mp4state.mp4file, mp4state.mp4track);
-        mp4state.sampleId = 1;
+        mp4state.numSamples = mp4ff_num_samples(mp4state.mp4file, mp4state.mp4track);
+        mp4state.sampleId = 0;
 
         module.is_seekable = 1;
     }
@@ -1712,8 +1610,10 @@
         NeAACDecClose(mp4state.hDecoder);
         if (mp4state.filetype)
             fclose(mp4state.aacfile);
-        else
-            MP4Close(mp4state.mp4file);
+        else {
+            mp4ff_close(mp4state.mp4file);
+            fclose(mp4state.mp4File);
+        }
         return -1;
     }
 
@@ -1728,8 +1628,10 @@
         NeAACDecClose(mp4state.hDecoder);
         if (mp4state.filetype)
             fclose(mp4state.aacfile);
-        else
-            MP4Close(mp4state.mp4file);
+        else {
+            mp4ff_close(mp4state.mp4file);
+            fclose(mp4state.mp4File);
+        }
         return -1;
     }
 
@@ -1765,7 +1667,8 @@
         {
             show_error(module.hMainWindow, "Cannot create playback thread");
             NeAACDecClose(mp4state.hDecoder);
-            MP4Close(mp4state.mp4file);
+            mp4ff_close(mp4state.mp4file);
+            fclose(mp4state.mp4File);
             return -1;
         }
     }
@@ -1855,8 +1758,10 @@
     NeAACDecClose(mp4state.hDecoder);
     if (mp4state.filetype)
         fclose(mp4state.aacfile);
-    else
-        MP4Close(mp4state.mp4file);
+    else {
+        mp4ff_close(mp4state.mp4file);
+        fclose(mp4state.mp4File);
+    }
 
     module.outMod->Close();
     module.SAVSADeInit();
@@ -1871,25 +1776,34 @@
     if(!stricmp(fn + strlen(fn) - 3,"MP4") || !stricmp(fn + strlen(fn) - 3,"M4A"))
     {
         int track;
-        MP4Duration length;
-        MP4FileHandle file;
+        int64_t length;
+        FILE *mp4File;
+        mp4ff_t *file;
+        mp4ff_callback_t mp4cb = {0};
 
-        file = MP4Read(fn, 0);
-        if (!file)
+        mp4File = fopen(fn, "rb");
+        mp4cb.read = read_callback;
+        mp4cb.seek = seek_callback;
+        mp4cb.user_data = mp4File;
+
+
+        file = mp4ff_open_read(&mp4cb);
+        if (file == NULL)
             return 0;
 
         if ((track = GetAACTrack(file)) < 0)
         {
-            MP4Close(file);
+            mp4ff_close(file);
+            fclose(mp4File);
             return -1;
         }
 
-        length = MP4GetTrackDuration(file, track);
+        length = mp4ff_get_track_duration(file, track);
 
-        msDuration = MP4ConvertFromTrackDuration(file, track,
-            length, MP4_MSECS_TIME_SCALE);
+        msDuration = (long)((float)length / (float)mp4ff_time_scale(file, track) + 0.5);
 
-        MP4Close(file);
+        mp4ff_close(file);
+        fclose(mp4File);
 
         return msDuration;
     } else {
@@ -2001,7 +1915,7 @@
     {
         int track;
         long msDuration;
-        MP4Duration length;
+        long length;
 
         if ((track = GetAACTrack(mp4state.mp4file)) < 0)
         {
@@ -2008,10 +1922,9 @@
             return -1;
         }
 
-        length = MP4GetTrackDuration(mp4state.mp4file, track);
+        length = mp4ff_get_track_duration(mp4state.mp4file, track);
 
-        msDuration = MP4ConvertFromTrackDuration(mp4state.mp4file, track,
-            length, MP4_MSECS_TIME_SCALE);
+        msDuration = (long)(length*1000.0 / (float)mp4ff_time_scale(mp4state.mp4file, track) + 0.5);
 
         return msDuration;
     } else {
@@ -2060,17 +1973,40 @@
 
         if (title)
         {
-            MP4FileHandle file = MP4_INVALID_FILE_HANDLE;
-            if (!(file = MP4Read(filename, 0)))
+            unsigned char header[8];
+            FILE *hMP4File = fopen(filename, "rb");
+            if (!hMP4File)
             {
+                return;
+            }
+            fread(header, 1, 8, hMP4File);
+            fclose(hMP4File);
+
+            if (header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p')
+            {
+                FILE *mp4File;
+                mp4ff_t *file;
+                mp4ff_callback_t mp4cb = {0};
+
+                mp4File = fopen(filename, "rb");
+                mp4cb.read = read_callback;
+                mp4cb.seek = seek_callback;
+                mp4cb.user_data = mp4File;
+
+                file = mp4ff_open_read(&mp4cb);
+                if (file == NULL)
+                    return;
+
+                ConstructTitle(file, filename, title, titleformat);
+
+                mp4ff_close(file);
+                fclose(mp4File);
+            } else {
                 char *tmp2;
                 char *tmp = PathFindFileName(filename);
                 strcpy(title, tmp);
                 tmp2 = strrchr(title, '.');
                 tmp2[0] = '\0';
-            } else {
-                ConstructTitle(file, filename, title, titleformat);
-                MP4Close(file);
             }
         }
     }
@@ -2180,13 +2116,13 @@
         /* seeking */
         if (mp4state.seek_needed != -1)
         {
-            MP4Duration duration;
+            int64_t duration;
+            int32_t skip_samples = 0;
 
             module.outMod->Flush(mp4state.decode_pos_ms);
-            duration = MP4ConvertToTrackDuration(mp4state.mp4file,
-                mp4state.mp4track, mp4state.seek_needed, MP4_MSECS_TIME_SCALE);
-            mp4state.sampleId = MP4GetSampleIdFromTime(mp4state.mp4file,
-                mp4state.mp4track, duration, 0);
+            duration = (int64_t)(mp4state.seek_needed/1000.0 * mp4state.samplerate + 0.5);
+            mp4state.sampleId = mp4ff_find_sample_use_offsets(mp4state.mp4file,
+                mp4state.mp4track, duration, &skip_samples);
 
             mp4state.decode_pos_ms = mp4state.seek_needed;
             mp4state.seek_needed = -1;
@@ -2214,7 +2150,7 @@
 
                 /* for gapless decoding */
                 char *buf;
-                MP4Duration dur;
+                long dur;
                 unsigned int sample_count;
                 unsigned int delay = 0;
 
@@ -2222,10 +2158,10 @@
                 buffer = NULL;
                 buffer_size = 0;
 
-                rc = MP4ReadSample(mp4state.mp4file, mp4state.mp4track,
-                    mp4state.sampleId++, &buffer, &buffer_size,
-                    NULL, &dur, NULL, NULL);
-                if (mp4state.sampleId-1 == 1) dur = 0;
+                dur = mp4ff_get_sample_duration(mp4state.mp4file, mp4state.mp4track, mp4state.sampleId);
+                rc = mp4ff_read_sample(mp4state.mp4file, mp4state.mp4track, mp4state.sampleId++, &buffer,  &buffer_size);
+
+                if (mp4state.sampleId == 1) dur = 0;
                 if (rc == 0 || buffer == NULL)
                 {
                     mp4state.last_frame = 1;
@@ -2638,18 +2574,17 @@
 
 /* new Media Library interface */
 
-int mp4_get_metadata(MP4FileHandle file, const char *item, char *dest, int dlen)
+int mp4_get_metadata(mp4ff_t *file, const char *item, char *dest, int dlen)
 {
     char *pVal = NULL, dummy1[4096];
-    short dummy = 0, dummy2 = 0;
 
     if (dlen < 1) return 0;
 
     if (!stricmp(item, "track") || !stricmp(item, "tracknumber"))
     {
-        if (MP4GetMetadataTrack(file, &dummy, &dummy2))
+        if (mp4ff_meta_get_track(file, &pVal))
         {
-            wsprintf(dummy1, "%d", (int)dummy);
+            wsprintf(dummy1, "%s", pVal);
             strncpy(dest, dummy1, dlen-1);
             dest[dlen-1] = '\0';
             return 1;
@@ -2657,9 +2592,9 @@
     }
     else if (!stricmp(item, "disc") || !stricmp(item, "disknumber"))
     {
-        if (MP4GetMetadataDisk(file, &dummy, &dummy2))
+        if (mp4ff_meta_get_disc(file, &pVal))
         {
-            wsprintf(dummy1, "%d", (int)dummy);
+            wsprintf(dummy1, "%s", pVal);
             strncpy(dest, dummy1, dlen-1);
             dest[dlen-1] = '\0';
             return 1;
@@ -2667,10 +2602,10 @@
     }
     else if (!stricmp(item, "compilation"))
     {
-        u_int8_t cpil = 0;
-        if (MP4GetMetadataCompilation(file, &cpil))
+        uint8_t cpil = 0;
+        if (mp4ff_meta_get_compilation(file, &pVal))
         {
-            wsprintf(dummy1, "%d", (int)cpil);
+            wsprintf(dummy1, "%s", pVal);
             strncpy(dest, dummy1, dlen-1);
             dest[dlen-1] = '\0';
             return 1;
@@ -2678,10 +2613,9 @@
     }
     else if (!stricmp(item, "tempo"))
     {
-        u_int16_t tempo = 0;
-        if (MP4GetMetadataTempo(file, &tempo))
+        if (mp4ff_meta_get_tempo(file, &pVal))
         {
-            wsprintf(dummy1, "%d", (int)tempo);
+            wsprintf(dummy1, "%s", pVal);
             strncpy(dest, dummy1, dlen-1);
             dest[dlen-1] = '\0';
             return 1;
@@ -2689,7 +2623,7 @@
     }
     else if (!stricmp(item, "artist"))
     {
-        if (MP4GetMetadataArtist(file, &pVal))
+        if (mp4ff_meta_get_artist(file, &pVal))
         {
             strncpy(dest, pVal, dlen-1);
             dest[dlen-1] = '\0';
@@ -2698,7 +2632,7 @@
     }
     else if (!stricmp(item, "writer"))
     {
-        if (MP4GetMetadataWriter(file, &pVal))
+        if (mp4ff_meta_get_writer(file, &pVal))
         {
             strncpy(dest, pVal, dlen-1);
             dest[dlen-1] = '\0';
@@ -2707,7 +2641,7 @@
     }
     else if (!stricmp(item, "title"))
     {
-        if (MP4GetMetadataName(file, &pVal))
+        if (mp4ff_meta_get_title(file, &pVal))
         {
             strncpy(dest, pVal, dlen-1);
             dest[dlen-1] = '\0';
@@ -2716,7 +2650,7 @@
     }
     else if (!stricmp(item, "album"))
     {
-        if (MP4GetMetadataAlbum(file, &pVal))
+        if (mp4ff_meta_get_album(file, &pVal))
         {
             strncpy(dest, pVal, dlen-1);
             dest[dlen-1] = '\0';
@@ -2725,7 +2659,7 @@
     }
     else if (!stricmp(item, "date") || !stricmp(item, "year"))
     {
-        if (MP4GetMetadataYear(file, &pVal))
+        if (mp4ff_meta_get_date(file, &pVal))
         {
             strncpy(dest, pVal, dlen-1);
             dest[dlen-1] = '\0';
@@ -2734,7 +2668,7 @@
     }
     else if (!stricmp(item, "comment"))
     {
-        if (MP4GetMetadataComment(file, &pVal))
+        if (mp4ff_meta_get_comment(file, &pVal))
         {
             strncpy(dest, pVal, dlen-1);
             dest[dlen-1] = '\0';
@@ -2743,7 +2677,7 @@
     }
     else if (!stricmp(item, "genre"))
     {
-        if (MP4GetMetadataGenre(file, &pVal))
+        if (mp4ff_meta_get_genre(file, &pVal))
         {
             strncpy(dest, pVal, dlen-1);
             dest[dlen-1] = '\0';
@@ -2752,7 +2686,7 @@
     }
     else if (!stricmp(item, "tool"))
     {
-        if (MP4GetMetadataTool(file, &pVal))
+        if (mp4ff_meta_get_tool(file, &pVal))
         {
             strncpy(dest, pVal, dlen-1);
             dest[dlen-1] = '\0';
@@ -2759,10 +2693,11 @@
             return 1;
         }
     }
+#if 0
     else
     {
-        u_int32_t valueSize = 0;
-        u_int8_t *pValue = NULL;
+        uint32_t valueSize = 0;
+        uint8_t *pValue = NULL;
 
         if (MP4GetMetadataFreeForm(file, (char *)item, &pValue, &valueSize))
         {
@@ -2772,6 +2707,7 @@
             return 1;
         }
     }
+#endif
 
     return 0;
 }
@@ -2793,9 +2729,21 @@
     else
     {
         char temp[2048], temp2[2048];
-        MP4FileHandle file = MP4Read(fn, 0);
-        if (file == MP4_INVALID_FILE_HANDLE) return 0;
+        FILE *mp4File;
+        mp4ff_callback_t mp4cb = {0};
+        mp4ff_t *file;
 
+        mp4File = fopen(fn, "rb");
+        mp4cb.read = read_callback;
+        mp4cb.seek = seek_callback;
+        mp4cb.write = write_callback;
+        mp4cb.truncate = truncate_callback;
+        mp4cb.user_data = mp4File;
+
+
+        file = mp4ff_open_read(&mp4cb);
+        if (file == NULL) return 0;
+
         if (mp4_get_metadata(file, data, temp, sizeof(temp)))
         {
             int len = ConvertUTF8ToANSI(temp, temp2);
@@ -2804,13 +2752,14 @@
             dest[len] = '\0';
         }
 
-        MP4Close(file);
+        mp4ff_close(file);
+        fclose(mp4File);
     }
 
     return 1;
 }
 
-static struct medialib_tags mltags = {0, 0};
+static mp4ff_metadata_t mltags = {0, 0};
 static BOOL medialib_init = FALSE;
 static char medialib_lastfn[2048] = "";
 
@@ -2820,15 +2769,27 @@
     char *temp;
 
     if (!medialib_init || (medialib_init && stricmp(fn, medialib_lastfn))) {
-        MP4FileHandle file;
+        FILE *mp4File;
+        mp4ff_callback_t mp4cb = {0};
+        mp4ff_t *file;
         strcpy(medialib_lastfn, fn);
 
         if (medialib_init) tag_delete(&mltags);
 
-        file = MP4Read(fn, 0);
-        if (file == MP4_INVALID_FILE_HANDLE) return 0;
+        mp4File = fopen(medialib_lastfn, "rb");
+        mp4cb.read = read_callback;
+        mp4cb.seek = seek_callback;
+        mp4cb.user_data = mp4File;
+
+
+        file = mp4ff_open_read(&mp4cb);
+        if (file == NULL) return 0;
+
         ReadMP4Tag(file, &mltags);
-        MP4Close(file);
+
+        mp4ff_close(file);
+        fclose(mp4File);
+
         medialib_init = TRUE;
     }
 
@@ -2851,18 +2812,19 @@
 {
     if (medialib_init)
     {
-        MP4FileHandle file = MP4Modify(medialib_lastfn, 0, 0);
-        if (file == MP4_INVALID_FILE_HANDLE) return 0;
+        FILE *mp4File;
+        mp4ff_callback_t mp4cb = {0};
 
-        MP4MetadataDelete(file);
-        MP4Close(file);
+        mp4File = fopen(medialib_lastfn, "rb+");
+        mp4cb.read = read_callback;
+        mp4cb.seek = seek_callback;
+        mp4cb.write = write_callback;
+        mp4cb.truncate = truncate_callback;
+        mp4cb.user_data = mp4File;
 
-        file = MP4Modify(medialib_lastfn, 0, 0);
-        if (file == MP4_INVALID_FILE_HANDLE) return 0;
+        mp4ff_meta_update(&mp4cb, &mltags);
 
-        WriteMP4Tag(file, &mltags);
-
-        MP4Close(file);
+        fclose(mp4File);
 
         return 1;
     }
--- a/plugins/in_mp4/in_mp4.dsp
+++ b/plugins/in_mp4/in_mp4.dsp
@@ -43,7 +43,7 @@
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O1 /I "..\..\include" /I "..\..\common\mp4v2" /I "..\..\common\mp4av" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O1 /I "..\..\include" /I "..\..\common\mp4v2" /I "..\..\common\mp4av" /I "..\..\common\mp4ff" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
 # ADD BASE RSC /l 0x413 /d "NDEBUG"
@@ -69,7 +69,7 @@
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\include" /I "..\..\common\mp4v2" /I "..\..\common\mp4av" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\include" /I "..\..\common\mp4v2" /I "..\..\common\mp4av" /I "..\..\common\mp4ff" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
 # ADD BASE RSC /l 0x413 /d "_DEBUG"
@@ -92,10 +92,6 @@
 # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
 # Begin Source File
 
-SOURCE=.\aac2mp4.cpp
-# End Source File
-# Begin Source File
-
 SOURCE=.\aacinfo.c
 # End Source File
 # Begin Source File
@@ -125,6 +121,14 @@
 # Begin Source File
 
 SOURCE=.\in2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\common\mp4ff\mp4ff.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\common\mp4ff\mp4ff_int_types.h
 # End Source File
 # Begin Source File
 
--- a/plugins/in_mp4/in_mp4.dsw
+++ b/plugins/in_mp4/in_mp4.dsw
@@ -15,11 +15,8 @@
     Project_Dep_Name libfaad
     End Project Dependency
     Begin Project Dependency
-    Project_Dep_Name libmp4v2_st
+    Project_Dep_Name mp4ff
     End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name libmp4av_st
-    End Project Dependency
 }}}
 
 ###############################################################################
@@ -36,19 +33,7 @@
 
 ###############################################################################
 
-Project: "libmp4av_st"=..\..\common\mp4av\libmp4av_st.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "libmp4v2_st"=..\..\common\mp4v2\libmp4v2_st60.dsp - Package Owner=<4>
+Project: "mp4ff"=..\..\common\mp4ff\mp4ff.dsp - Package Owner=<4>
 
 Package=<5>
 {{{
--- a/plugins/in_mp4/in_mp4.rc
+++ b/plugins/in_mp4/in_mp4.rc
@@ -63,23 +63,16 @@
     EDITTEXT        IDC_METAWRITER,53,127,151,14,ES_AUTOHSCROLL
     EDITTEXT        IDC_METAALBUM,53,145,233,14,ES_AUTOHSCROLL
     EDITTEXT        IDC_METACOMMENTS,53,163,234,35,ES_AUTOHSCROLL
-    EDITTEXT        IDC_METAGENRE,53,202,91,14,ES_AUTOHSCROLL
+    EDITTEXT        IDC_METAGENRE,53,202,151,14,ES_AUTOHSCROLL
     EDITTEXT        IDC_METAYEAR,234,91,52,14,ES_AUTOHSCROLL
-    EDITTEXT        IDC_METATRACK1,234,109,17,14,ES_AUTOHSCROLL
-    EDITTEXT        IDC_METATRACK2,269,109,17,14,ES_AUTOHSCROLL
-    EDITTEXT        IDC_METADISK1,234,127,17,14,ES_AUTOHSCROLL
-    EDITTEXT        IDC_METADISK2,269,127,17,14,ES_AUTOHSCROLL
-    EDITTEXT        IDC_METATEMPO,175,202,22,14,ES_AUTOHSCROLL
+    EDITTEXT        IDC_METATRACK1,234,109,52,14,ES_AUTOHSCROLL
+    EDITTEXT        IDC_METADISK1,234,127,52,14,ES_AUTOHSCROLL
     CONTROL         "Part of a compilation",IDC_METACOMPILATION,"Button",
                     BS_AUTOCHECKBOX | WS_TABSTOP,207,202,80,14
     DEFPUSHBUTTON   "OK",IDOK,246,234,50,14
     PUSHBUTTON      "Cancel",IDCANCEL,186,234,50,14
-    PUSHBUTTON      "Convert Now!",IDC_CONVERT,111,166,81,14
-    CTEXT           "You can convert this file to MP4 if you like. This does not involve re-encoding, only the container format is changed. Advantages of MP4 files are that they are playable by a lot more players and they will have a lot of support in the future.",
-                    IDC_CONVERT1,45,103,214,36
     LTEXT           "",IDC_INFOTEXT,14,17,275,47,0,WS_EX_CLIENTEDGE
     GROUPBOX        "User data",IDC_USERDATA,7,76,289,151
-    GROUPBOX        "Convert to MP4",IDC_CONVERT2,7,81,289,145
     LTEXT           "Name",IDC_STATIC1,13,91,20,14,SS_CENTERIMAGE
     LTEXT           "Artist",IDC_STATIC2,13,109,16,14,SS_CENTERIMAGE
     LTEXT           "Composer",IDC_STATIC3,13,127,32,14,SS_CENTERIMAGE
@@ -89,9 +82,6 @@
     LTEXT           "Disc",IDC_STATIC9,211,127,15,14,SS_CENTERIMAGE
     LTEXT           "Track",IDC_STATIC8,211,109,20,14,SS_CENTERIMAGE
     LTEXT           "Genre",IDC_STATIC6,13,202,20,14,SS_CENTERIMAGE
-    LTEXT           "BPM",IDC_STATIC12,153,202,16,14,SS_CENTERIMAGE
-    LTEXT           "of",IDC_STATIC10,257,109,8,14,SS_CENTERIMAGE
-    LTEXT           "of",IDC_STATIC11,257,127,8,14,SS_CENTERIMAGE
 END
 
 IDD_CONFIG DIALOG DISCARDABLE  0, 0, 233, 166
--- a/plugins/in_mp4/utils.c
+++ b/plugins/in_mp4/utils.c
@@ -22,12 +22,13 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: utils.c,v 1.7 2004/03/04 19:06:01 menno Exp $
+** $Id: utils.c,v 1.8 2004/09/03 19:38:32 menno Exp $
 **/
 
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
-#include <mp4.h>
+//#include <mp4.h>
+#include <mp4ff.h>
 #include <neaacdec.h>
 #include "utils.h"
 
@@ -47,34 +48,28 @@
     return c1 - c2;
 }
 
-int GetAACTrack(MP4FileHandle infile)
+int GetAACTrack(mp4ff_t *infile)
 {
     /* find AAC track */
     int i, rc;
-	int numTracks = MP4GetNumberOfTracks(infile, NULL, 0);
+    int numTracks = mp4ff_total_tracks(infile);
 
-	for (i = 0; i < numTracks; i++)
+    for (i = 0; i < numTracks; i++)
     {
-        MP4TrackId trackId = MP4FindTrackId(infile, i, NULL, 0);
-        const char* trackType = MP4GetTrackType(infile, trackId);
+        unsigned char *buff = NULL;
+        int buff_size = 0;
+        mp4AudioSpecificConfig mp4ASC;
 
-        if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE))
+        mp4ff_get_decoder_config(infile, i, &buff, &buff_size);
+
+        if (buff)
         {
-            unsigned char *buff = NULL;
-            int buff_size = 0;
-            mp4AudioSpecificConfig mp4ASC;
+            rc = NeAACDecAudioSpecificConfig(buff, buff_size, &mp4ASC);
+            free(buff);
 
-            MP4GetTrackESConfiguration(infile, trackId, &buff, &buff_size);
-
-            if (buff)
-            {
-                rc = AudioSpecificConfig(buff, buff_size, &mp4ASC);
-                free(buff);
-
-                if (rc < 0)
-                    return -1;
-                return trackId;
-            }
+            if (rc < 0)
+                continue;
+            return i;
         }
     }
 
@@ -82,6 +77,7 @@
     return -1;
 }
 
+#if 0
 int GetAudioTrack(MP4FileHandle infile)
 {
     /* find AAC track */
@@ -123,6 +119,7 @@
     /* can't decode this */
     return -1;
 }
+#endif
 
 LPTSTR PathFindFileName(LPCTSTR pPath)
 {
--- a/plugins/in_mp4/utils.h
+++ b/plugins/in_mp4/utils.h
@@ -22,18 +22,19 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: utils.h,v 1.3 2003/07/29 08:20:14 menno Exp $
+** $Id: utils.h,v 1.4 2004/09/03 19:38:32 menno Exp $
 **/
 
 #ifndef UTILS_INCLUDED
 #define UTILS_INCLUDED
 
-#include <mp4.h>
+//#include <mp4.h>
+#include <mp4ff.h>
 
 LPTSTR PathFindFileName(LPCTSTR pPath);
-int GetVideoTrack(MP4FileHandle infile);
-int GetAudioTrack(MP4FileHandle infile);
-int GetAACTrack(MP4FileHandle infile);
+//int GetVideoTrack(MP4FileHandle infile);
+//int GetAudioTrack(MP4FileHandle infile);
+int GetAACTrack(mp4ff_t *infile);
 int StringComp(char const *str1, char const *str2, unsigned long len);
 char *convert3in4to3in3(void *sample_buffer, int samples);