Index: src/atoms.c
===================================================================
--- src/atoms.c	(revision 122)
+++ src/atoms.c	(working copy)
@@ -46,10 +46,17 @@
 
 AtomSMHD *atom_smhd_new();
 AtomVMHD *atom_vmhd_new();
-AtomMP4A *atom_mp4a_new();
-AtomMP4V *atom_mp4v_new();
+SampleTableEntryMP4A *sample_entry_mp4a_new();
+SampleTableEntryMP4V *sample_entry_mp4v_new();
 AtomFull *atom_alis_new();
 
+static guint64 atom_info_list_get_size (GList *ai);
+static void atom_info_list_free (GList *ai);
+static guint64 atom_info_list_copy_data (GList *ai,
+     guint8 *buffer, guint64 size, guint64 *offset);
+static GList *atom_info_list_prepend_atom (GList *ai, Atom *atom,
+    AtomGetSizeFunc size_func, AtomCopyDataFunc copy_func,
+    AtomFreeFunc free_func);
 
 guint64 get_current_qt_time() {
   GTimeVal timeval;
@@ -473,21 +480,21 @@
   }
 }
 
-void atom_sample_entry_init(AtomSampleEntry *se, guint32 type) {
+void atom_sample_entry_init(SampleTableEntry *se, guint32 type) {
   atom_header_set(&se->header, type, 0, 0);
 
   memset(se->reserved, 0, sizeof(guint8) * 6);
   se->data_reference_index = 0;
 }
 
-void atom_esds_init(AtomESDS *esds) {
+static void atom_esds_init(AtomESDS *esds) {
   guint8 flags[3] = {0,0,0};
   atom_full_init(&esds->header, FOURCC_esds, 0, 0, 0, flags);
 
   desc_es_init(&esds->es);
 }
 
-void atom_mp4a_init(AtomMP4A *mp4a) {
+void sample_entry_mp4a_init(SampleTableEntryMP4A *mp4a) {
   atom_sample_entry_init(&mp4a->se, FOURCC_mp4a);
 
   mp4a->version = 0;
@@ -504,10 +511,10 @@
   mp4a->bytes_per_frame = 0;
   mp4a->bytes_per_sample = 0;
 
-  mp4a->es = NULL;
+  mp4a->extension_atoms = NULL;
 }
 
-void atom_mp4v_init(AtomMP4V *mp4v, AtomsContext *context) {
+void sample_entry_mp4v_init(SampleTableEntryMP4V *mp4v, AtomsContext *context) {
   atom_sample_entry_init(&mp4v->se, FOURCC_mp4v);
 
   mp4v->version = 0;
@@ -742,15 +749,15 @@
   return ftyp;
 }
 
-AtomMP4A * atom_mp4a_new() {
-  AtomMP4A *mp4a = g_new0(AtomMP4A, 1);
-  atom_mp4a_init(mp4a);
+SampleTableEntryMP4A * sample_entry_mp4a_new() {
+  SampleTableEntryMP4A *mp4a = g_new0(SampleTableEntryMP4A, 1);
+  sample_entry_mp4a_init(mp4a);
   return mp4a;
 }
 
-AtomMP4V * atom_mp4v_new(AtomsContext *context) {
-  AtomMP4V *mp4v = g_new0(AtomMP4V, 1);
-  atom_mp4v_init(mp4v, context);
+SampleTableEntryMP4V * sample_entry_mp4v_new(AtomsContext *context) {
+  SampleTableEntryMP4V *mp4v = g_new0(SampleTableEntryMP4V, 1);
+  sample_entry_mp4v_init(mp4v, context);
   return mp4v;
 }
 
@@ -809,14 +816,24 @@
   return esds;
 }
 
+AtomFRMA *atom_frma_new() {
+  AtomFRMA *frma = g_new0(AtomFRMA, 1);
+  atom_header_set(&frma->header, FOURCC_frma, 0, 0);
+  return frma;
+}
+
 AtomData *atom_data_new(guint32 fourcc) {
   AtomData *data = g_new0(AtomData, 1);
   atom_header_set(&data->header, fourcc, 0, 0);
-  data->data = NULL;
-  data->datalen = 0;
   return data;
 }
 
+AtomWAVE *atom_wave_new() {
+  AtomWAVE *wave = g_new0(AtomWAVE, 1);
+  atom_header_set(&wave->header, FOURCC_wave, 0, 0);
+  return wave;
+}
+
 /*
  * Fourcc is the tag fourcc
  * flags will be truncated to 24bits
@@ -937,32 +954,86 @@
   desc_es_descriptor_clear(&esds->es);
   g_free(esds);
 }
-void atom_sample_entry_free(AtomSampleEntry *se) {
+
+static void
+atom_frma_free(AtomFRMA *frma) {
+  atom_clear(&frma->header);
+  g_free(frma);
+}
+
+void atom_sample_entry_free(SampleTableEntry *se) {
   atom_clear(&se->header);
 }
 
-void atom_mp4a_free(AtomMP4A *mp4a) {
-  atom_sample_entry_free(&mp4a->se);
-  if (mp4a->es != NULL) {
-    atom_esds_free(mp4a->es);
-    mp4a->es = NULL;
+static guint64
+atom_info_list_get_size (GList *ai)
+{
+  guint64 size = 0;
+
+  while (ai) {
+    AtomInfo *info = (AtomInfo*)ai->data;
+    size += info->get_size_func(info->atom);
+    ai = g_list_next(ai);
   }
-  g_free(mp4a);
+
+  return size;
 }
 
-void atom_mp4v_free(AtomMP4V *mp4v) {
-  GList *walker;
-  atom_sample_entry_free(&mp4v->se);
-  walker = mp4v->extra_atoms;
-  while(walker) {
-    GList *aux = walker;
-    walker = g_list_next(walker);
-    mp4v->extra_atoms = g_list_remove_link(mp4v->extra_atoms, aux);
-    AtomInfo *info = (AtomInfo*) aux->data;
+static void
+atom_info_list_free (GList *ai)
+{
+  while (ai) {
+    AtomInfo *info = (AtomInfo*) ai->data;
     info->free_func(info->atom);
     g_free(info);
-    g_list_free(aux);
+
+    ai = g_list_delete_link (ai, ai);
   }
+}
+
+static guint64
+atom_info_list_copy_data (GList *ai, guint8 *buffer,
+    guint64 size, guint64 *offset)
+{
+  guint64 original_offset = *offset;
+
+  while(ai) {
+    AtomInfo *info = (AtomInfo*) ai->data;
+    if (!info->copy_data_func(info->atom, buffer, size, offset)) {
+      return 0;
+    }
+    ai = g_list_next(ai);
+  }
+
+  return *offset - original_offset;
+}
+
+static GList *
+atom_info_list_prepend_atom (GList *ai, Atom *atom,
+    AtomGetSizeFunc size_func, AtomCopyDataFunc copy_func,
+    AtomFreeFunc free_func)
+{
+  AtomInfo *info = g_new0(AtomInfo, 1);
+
+  info->atom = atom;
+  info->get_size_func = size_func;
+  info->copy_data_func = copy_func;
+  info->free_func = free_func;
+
+  return g_list_prepend(ai, info);
+}
+
+static void
+sample_entry_mp4a_free(SampleTableEntryMP4A *mp4a) {
+  atom_sample_entry_free(&mp4a->se);
+  atom_info_list_free(mp4a->extension_atoms);
+  g_free(mp4a);
+}
+
+static void
+sample_entry_mp4v_free(SampleTableEntryMP4V *mp4v) {
+  atom_sample_entry_free(&mp4v->se);
+  atom_info_list_free(mp4v->extra_atoms);
   g_free(mp4v);
 }
 
@@ -974,14 +1045,14 @@
     GList *aux = walker;
     walker = g_list_next(walker);
     stsd->entries = g_list_remove_link(stsd->entries, aux);
-    AtomSampleEntry *se = (AtomSampleEntry*)aux->data;
+    SampleTableEntry *se = (SampleTableEntry*)aux->data;
 
     switch(se->kind) {
       case AUDIO:
-        atom_mp4a_free((AtomMP4A*)se);
+        sample_entry_mp4a_free((SampleTableEntryMP4A*)se);
         break;
       case VIDEO:
-        atom_mp4v_free((AtomMP4V*)se);
+        sample_entry_mp4v_free((SampleTableEntryMP4V*)se);
         break;
       default: //we cleanup our best
         atom_sample_entry_free(se);
@@ -1180,6 +1251,12 @@
   g_free(moov);
 }
 
+void atom_wave_free(AtomWAVE *wave) {
+  atom_clear(&wave->header);
+  atom_info_list_free(wave->extension_atoms);
+  g_free(wave);
+}
+
 /* - END OF DESTRUCTOR FUNCTIONS - */
 
 guint64 atom_data_get_size(AtomData *data) {
@@ -1268,14 +1345,14 @@
   return atom_full_set_size(&url->header, size);
 }
 
-guint64 atom_sample_entry_set_size(AtomSampleEntry *se, guint64 size) {
+guint64 atom_sample_entry_set_size(SampleTableEntry *se, guint64 size) {
   size += sizeof(guint8) * 6;
   size += sizeof(guint16);
 
   return atom_set_size(&se->header, size);
 }
 
-guint64 atom_sample_entry_get_size(AtomSampleEntry *se) {
+guint64 atom_sample_entry_get_size(SampleTableEntry *se) {
   return atom_get_size(&se->header);
 }
 
@@ -1286,6 +1363,13 @@
   return atom_full_set_size(&esds->header, size);
 }
 
+static guint64
+atom_frma_get_size(AtomFRMA *frma) {
+  guint64 size = sizeof(guint32);
+
+  return atom_set_size(&frma->header, size);
+}
+
 guint64 atom_hint_sample_entry_get_size(AtomHintSampleEntry *hse) {
   guint64 size = 0;
   size += hse->size * sizeof(guint8);
@@ -1293,14 +1377,14 @@
   return atom_sample_entry_set_size(&hse->se, size);
 }
 
-guint64 atom_mp4s_get_size(AtomMP4S *mp4s) {
+guint64 atom_mp4s_get_size(SampleTableEntryMP4S *mp4s) {
   guint64 size = 0;
   size += atom_esds_get_size(&mp4s->es);
 
   return atom_sample_entry_set_size(&mp4s->se, size);
 }
 
-guint64 atom_mp4a_get_size(AtomMP4A *mp4a) {
+guint64 sample_entry_mp4a_get_size(SampleTableEntryMP4A *mp4a) {
   guint64 size = 0;
 
   size += sizeof(guint16) * 2;
@@ -1312,30 +1396,21 @@
     size += sizeof(guint32)*4;
   }
 
-  if (mp4a->es) {
-    size += atom_esds_get_size(mp4a->es);
-  }
+  size += atom_info_list_get_size(mp4a->extension_atoms);
 
   size = atom_sample_entry_set_size(&mp4a->se, size);
   return size;
 }
 
-guint64 atom_mp4v_get_size(AtomMP4V *mp4v) {
+guint64 sample_entry_mp4v_get_size(SampleTableEntryMP4V *mp4v) {
   guint64 size = 0;
-  GList *walker;
-  AtomInfo *info;
 
   size += sizeof(guint16) * 7;
   size += sizeof(guint32) * 6;
   size += sizeof(guint8) * 32;
 
   //extra atoms
-  walker = mp4v->extra_atoms;
-  while (walker) {
-    info = (AtomInfo*)walker->data;
-    size += info->get_size_func(info->atom);
-    walker = g_list_next(walker);
-  }
+  size += atom_info_list_get_size(mp4v->extra_atoms);
 
 //  size += atom_esds_get_size(&mp4a->es);
 
@@ -1350,22 +1425,22 @@
 
   walker = stsd->entries;
   while(walker != NULL) {
-    AtomSampleEntry *se = (AtomSampleEntry*)walker->data;
+    SampleTableEntry *se = (SampleTableEntry*)walker->data;
     switch(se->header.type) {
       case FOURCC_mp4s:
-        size += atom_mp4s_get_size((AtomMP4S*)se);
+        size += atom_mp4s_get_size((SampleTableEntryMP4S*)se);
         break;
       case FOURCC_mp4a:
-        size += atom_mp4a_get_size((AtomMP4A*)se);
+        size += sample_entry_mp4a_get_size((SampleTableEntryMP4A*)se);
         break;
       case FOURCC_mp4v:
-        size += atom_mp4v_get_size((AtomMP4V*)se);
+        size += sample_entry_mp4v_get_size((SampleTableEntryMP4V*)se);
         break;
       default:
         if (se->kind == VIDEO) {
-          size += atom_mp4v_get_size((AtomMP4V*)se);
+          size += sample_entry_mp4v_get_size((SampleTableEntryMP4V*)se);
         } else if (se->kind == AUDIO) {
-          size += atom_mp4a_get_size((AtomMP4A*)se);
+          size += sample_entry_mp4a_get_size((SampleTableEntryMP4A*)se);
         } else {
           size += atom_hint_sample_entry_get_size((AtomHintSampleEntry*)walker->data);
         }
@@ -1624,6 +1699,16 @@
   return size;
 }
 
+guint64 atom_wave_get_size(AtomWAVE *atom) {
+  guint64 size = 0;
+
+  if (atom->extension_atoms)
+    size += atom_info_list_get_size(atom->extension_atoms);
+  size = atom_set_size(&(atom->header), size);
+
+  return size;
+}
+
 /* COPY DATA FUNCTIONS */
 guint64 atom_data_copy_data(AtomData *data, guint8 *buffer, guint64 size, guint64 *offset) {
   guint64 original_offset = *offset;
@@ -1635,7 +1720,8 @@
   if (!atom_copy_data(&data->header, buffer, size, offset)) {
           return 0;
   }
-  prop_copy_uint8_array(data->data, data->datalen, buffer, offset);
+  if (data->datalen)
+    prop_copy_uint8_array(data->data, data->datalen, buffer, offset);
   return *offset - original_offset;
 }
 guint64 atom_ftyp_copy_data(AtomFTYP *ftyp, guint8 *buffer, guint64 size, guint64 *offset) {
@@ -1914,7 +2000,7 @@
   return *offset - original_offset;
 }
 
-guint64 atom_sample_entry_copy_data(AtomSampleEntry *se, guint8 *buffer, guint64 size, guint64 *offset) {
+guint64 atom_sample_entry_copy_data(SampleTableEntry *se, guint8 *buffer, guint64 size, guint64 *offset) {
   guint64 original_offset = *offset;
   guint64 atom_size;
 
@@ -1952,10 +2038,30 @@
   return *offset - original_offset;
 }
 
-guint64 atom_mp4s_copy_data(AtomMP4S *mp4s, guint8 *buffer, guint64 size, guint64 *offset) {
+static guint64
+atom_frma_copy_data(AtomFRMA *frma, guint8 *buffer,
+    guint64 size, guint64 *offset) {
   guint64 original_offset = *offset;
   guint64 atom_size;
 
+  atom_size = atom_frma_get_size(frma);
+  if (atom_size > size - *offset)
+    return 0;
+
+  if (!atom_copy_data(&(frma->header), buffer, size, offset))
+    return 0;
+
+  prop_copy_fourcc(frma->media_type, buffer, offset);
+
+  return *offset - original_offset;
+}
+
+guint64
+atom_mp4s_copy_data(SampleTableEntryMP4S *mp4s, guint8 *buffer, guint64 size,
+    guint64 *offset) {
+  guint64 original_offset = *offset;
+  guint64 atom_size;
+
   atom_size = atom_mp4s_get_size(mp4s);
   if (atom_size > size - *offset) {
     return 0;
@@ -1991,11 +2097,13 @@
   return *offset - original_offset;
 }
 
-guint64 atom_mp4a_copy_data(AtomMP4A *mp4a, guint8 *buffer, guint64 size, guint64 *offset) {
+guint64
+sample_entry_mp4a_copy_data(SampleTableEntryMP4A *mp4a, guint8 *buffer,
+    guint64 size, guint64 *offset) {
   guint64 original_offset = *offset;
   guint64 atom_size;
 
-  atom_size = atom_mp4a_get_size(mp4a);
+  atom_size = sample_entry_mp4a_get_size(mp4a);
   if (atom_size > size - *offset) {
     return 0;
   }
@@ -2020,22 +2128,21 @@
     prop_copy_uint32(mp4a->bytes_per_sample, buffer, offset);
   }
 
-  if (mp4a->es) {
-    if (!atom_esds_copy_data(mp4a->es, buffer, size, offset)) {
+  if (mp4a->extension_atoms) {
+    if (!atom_info_list_copy_data (mp4a->extension_atoms, buffer, size, offset))
       return 0;
-    }
   }
 
-
   return *offset - original_offset;
 }
 
-guint64 atom_mp4v_copy_data(AtomMP4V *mp4v, guint8 *buffer, guint64 size, guint64 *offset) {
+static guint64
+sample_entry_mp4v_copy_data(SampleTableEntryMP4V *mp4v, guint8 *buffer,
+    guint64 size, guint64 *offset) {
   guint64 original_offset = *offset;
   guint64 atom_size;
-  GList *walker;
 
-  atom_size = atom_mp4v_get_size(mp4v);
+  atom_size = sample_entry_mp4v_get_size(mp4v);
   if (atom_size > size - *offset) {
     return 0;
   }
@@ -2066,14 +2173,9 @@
   prop_copy_uint16(mp4v->color_table_id, buffer, offset);
 
   //extra atoms
-  walker = mp4v->extra_atoms;
-  while(walker) {
-    AtomInfo *info = (AtomInfo*) walker->data;
-    if (!info->copy_data_func(info->atom, buffer, size, offset)) {
-      return 0;
-    }
-    walker = g_list_next(walker);
-  }
+  if (mp4v->extra_atoms &&
+      !atom_info_list_copy_data (mp4v->extra_atoms, buffer, size, offset))
+    return 0;
 
 //  if (!atom_esds_copy_data(&mp4v->es, buffer, size, offset)) {
 //    return 0;
@@ -2237,30 +2339,36 @@
 
   walker = stsd->entries;
   while(walker) {
-    AtomSampleEntry *se = (AtomSampleEntry*) walker->data;
+    SampleTableEntry *se = (SampleTableEntry*) walker->data;
     switch(((Atom*)walker->data)->type) {
       case FOURCC_mp4a:
-        if (!atom_mp4a_copy_data((AtomMP4A*)walker->data, buffer, size, offset)) {
+        if (!sample_entry_mp4a_copy_data((SampleTableEntryMP4A*) walker->data,
+                buffer, size, offset)) {
           return 0;
         }
         break;
       case FOURCC_mp4s:
-        if (!atom_mp4s_copy_data((AtomMP4S*)walker->data, buffer, size, offset)) {
+        if (!atom_mp4s_copy_data((SampleTableEntryMP4S*) walker->data,
+                buffer, size, offset)) {
           return 0;
         }
         break;
       case FOURCC_mp4v:
-        if (!atom_mp4v_copy_data((AtomMP4V*)walker->data, buffer, size, offset)) {
+        if (!sample_entry_mp4v_copy_data((SampleTableEntryMP4V*) walker->data,
+                buffer, size, offset)) {
           return 0;
         }
         break;
       default:
         if (se->kind == VIDEO) {
-          size += atom_mp4v_copy_data((AtomMP4V*)walker->data, buffer, size, offset);
+          size += sample_entry_mp4v_copy_data((SampleTableEntryMP4V*) walker->data,
+                      buffer, size, offset);
         } else if (se->kind == AUDIO) {
-          size += atom_mp4a_copy_data((AtomMP4A*)walker->data, buffer, size, offset);
+          size += sample_entry_mp4a_copy_data((SampleTableEntryMP4A*) walker->data,
+                      buffer, size, offset);
         } else {
-          if(!atom_hint_sample_entry_copy_data((AtomHintSampleEntry*)walker->data, buffer, size, offset)) {
+          if (!atom_hint_sample_entry_copy_data(
+                  (AtomHintSampleEntry*) walker->data, buffer, size, offset)) {
             return 0;
           }
         }
@@ -2621,6 +2729,26 @@
   return *offset - original_offset;
 }
 
+guint64 atom_wave_copy_data(AtomWAVE *wave, guint8 *buffer,
+    guint64 size, guint64 *offset) {
+  guint64 original_offset = *offset;
+  guint64 atom_size;
+
+  atom_size = atom_wave_get_size(wave);
+  if (atom_size > size - *offset)
+    return 0;
+
+  if (!atom_copy_data(&(wave->header), buffer, size, offset))
+    return 0;
+
+  if (wave->extension_atoms) {
+    if (!atom_info_list_copy_data (wave->extension_atoms, buffer, size, offset))
+      return 0;
+  }
+
+  return *offset - original_offset;
+}
+
 /*
  * General functions
  */
@@ -2639,16 +2767,6 @@
   return data;
 }
 
-void atom_mp4v_add_extra_atom(AtomMP4V *mp4v, Atom* atom, AtomGetSizeFunc size_func,
-    AtomCopyDataFunc copy_func, AtomFreeFunc free_func) {
-  AtomInfo *info = g_new0(AtomInfo, 1);
-  info->atom = atom;
-  info->get_size_func = size_func;
-  info->copy_data_func = copy_func;
-  info->free_func = free_func;
-  mp4v->extra_atoms = g_list_append(mp4v->extra_atoms, info);
-}
-
 void atom_ctts_add_entry(AtomCTTS *ctts, guint32 nsamples, guint32 offset) {
   GList *walker = g_list_last(ctts->entries);
   CTTSEntry *entry = walker == NULL ? NULL : (CTTSEntry*) walker->data;
@@ -2679,7 +2797,7 @@
 
 guint32 atom_stsd_get_media_fourcc(AtomSTSD *stsd, guint32 index) {
   if (stsd->entries) {
-    AtomSampleEntry *entry = (AtomSampleEntry*)g_list_nth(stsd->entries, index)->data;
+    SampleTableEntry *entry = (SampleTableEntry*)g_list_nth(stsd->entries, index)->data;
     return entry->header.type;
   }
 
@@ -2693,7 +2811,7 @@
 gboolean atom_stsd_is_raw_audio(AtomSTSD *stsd) {
   //we only verify the first type
   if (stsd->entries != NULL) {
-    AtomSampleEntry *entry = (AtomSampleEntry*)g_list_first(stsd->entries)->data;
+    SampleTableEntry *entry = (SampleTableEntry*)g_list_first(stsd->entries)->data;
     if (entry->kind == AUDIO) {
       switch(entry->header.type) {
         case FOURCC_sowt:
@@ -2737,8 +2855,9 @@
 
 
 //TODO - what if there are other values in the table?
-AtomMP4A* atom_stsd_add_audio_entry(AtomSTSD *stsd, guint32 type) {
-  AtomMP4A *mp4a = atom_mp4a_new();
+static SampleTableEntryMP4A*
+atom_stsd_add_audio_entry(AtomSTSD *stsd, guint32 type) {
+  SampleTableEntryMP4A *mp4a = sample_entry_mp4a_new();
   mp4a->se.header.type = type;
   mp4a->se.kind = AUDIO;
   mp4a->compression_id = -1;
@@ -2747,8 +2866,9 @@
   return mp4a;
 }
 
-AtomMP4V* atom_stsd_add_video_entry(AtomSTSD *stsd, AtomsContext *context, guint32 type) {
-  AtomMP4V *mp4v = atom_mp4v_new(context);
+static SampleTableEntryMP4V*
+atom_stsd_add_video_entry(AtomSTSD *stsd, AtomsContext *context, guint32 type) {
+  SampleTableEntryMP4V *mp4v = sample_entry_mp4v_new(context);
   mp4v->se.header.type = type;
   mp4v->se.kind = VIDEO;
   mp4v->se.data_reference_index = 1;
@@ -2764,13 +2884,13 @@
 }
 
 gboolean atom_stsd_media_needs_stss(AtomSTSD *stsd, guint32 index) {
-  AtomSampleEntry *se;
+  SampleTableEntry *se;
   GList *walker = g_list_nth(stsd->entries, index);
   if (walker == NULL) {
     return FALSE;
   }
 
-  se = (AtomSampleEntry*) walker->data;
+  se = (SampleTableEntry*) walker->data;
   switch(se->header.type) {
     case FOURCC_h263:
     case FOURCC_avc1:
@@ -2845,57 +2965,119 @@
   trak->tkhd.height = height<<16;
 }
 
-AtomMP4A* atom_trak_set_generic_audio(AtomTRAK *trak, AtomsContext *context,
-    guint32 fourcc, guint32 rate, guint32 channels) {
+SampleTableEntryMP4A* atom_trak_set_generic_audio(AtomTRAK *trak,
+    AtomsContext *context, guint32 fourcc, guint32 rate, guint32 channels) {
+ SampleTableEntryMP4A *mp4a;
+
   atom_trak_set_audio_commons(trak, context, rate);
   if (channels > 2) {
     channels = 2;
   }
-  AtomMP4A *mp4a = atom_stsd_add_audio_entry(&trak->mdia.minf.stbl.stsd, fourcc);
+  mp4a = atom_stsd_add_audio_entry(&trak->mdia.minf.stbl.stsd, fourcc);
   mp4a->sample_rate = rate << 16; //adusting for fixed point 16.16
   mp4a->channels = channels;
   return mp4a;
 }
 
 void atom_trak_set_mp3(AtomTRAK *trak, AtomsContext *context, guint32 rate, guint32 channels) {
-  AtomMP4A *mp3 = atom_trak_set_generic_audio(trak, context, FOURCC__mp3, rate, channels);
+  SampleTableEntryMP4A *mp3 =
+      atom_trak_set_generic_audio(trak, context, FOURCC__mp3, rate, channels);
+
   mp3->version = 1;
   mp3->compression_id = -2;
+  mp3->samples_per_packet = 1152;
+  mp3->bytes_per_sample = 2;
 }
 
-void atom_trak_set_aac(AtomTRAK *trak, AtomsContext *context, guint32 rate, guint32 channels, const GstBuffer *codec_data) {
-  int i;
-  AtomMP4A *mp4a = atom_trak_set_generic_audio(trak, context, FOURCC_mp4a, rate, channels);
-  mp4a->es = atom_esds_new();
-  mp4a->es->es.dec_conf_desc.object_type = 64;
-  mp4a->es->es.dec_conf_desc.stream_type = 0x15;
-  mp4a->compression_id = 0;
+void 
+atom_trak_set_aac(AtomTRAK *trak, AtomsContext *context,
+    guint32 rate, guint32 channels, const GstBuffer *codec_data)
+{
+  SampleTableEntryMP4A *mp4a_se;
+  AtomWAVE *wave;
+  AtomFRMA *frma;
+  AtomESDS *esds;
+  Atom *ext_atom;
+  // AtomMP4A *mp4a_atom;
+  DecoderSpecificInfoDescriptor *desc;
 
+  mp4a_se =
+      atom_trak_set_generic_audio(trak, context, FOURCC_mp4a, rate, channels);
+  mp4a_se->version = 1;
+  mp4a_se->compression_id = -2;
+
+  /* Add WAVE atom to the MP4A sample table entry */
+  wave = atom_wave_new();
+  mp4a_se->extension_atoms =
+      atom_info_list_prepend_atom (mp4a_se->extension_atoms, (Atom *) wave,
+          (AtomGetSizeFunc) atom_wave_get_size,
+          (AtomCopyDataFunc) atom_wave_copy_data,
+          (AtomFreeFunc) atom_wave_free);
+
+  /* Prepend Terminator atom to the WAVE list first, so it ends up last */
+  ext_atom = (Atom *) atom_data_new (FOURCC_null);
+  wave->extension_atoms =
+      atom_info_list_prepend_atom (wave->extension_atoms, (Atom *) ext_atom,
+          (AtomGetSizeFunc) atom_data_get_size,
+          (AtomCopyDataFunc) atom_data_copy_data,
+          (AtomFreeFunc) atom_data_free);
+
+#if 0
+  /* Add MP4A atom to the WAVE */
+  mp4a_atom = atom_mp4a_new();
+
+  wave->extension_atoms =
+      atom_info_list_prepend_atom (wave->extension_atoms, (Atom *) mp4a_atom,
+          (AtomGetSizeFunc) atom_mp4a_get_size,
+          (AtomCopyDataFunc) atom_mp4a_copy_data,
+          (AtomFreeFunc) atom_mp4a_free);
+#endif
+
+  /* Add ESDS atom to WAVE */
+  esds = atom_esds_new();
+  esds->es.dec_conf_desc.object_type = 64;
+  esds->es.dec_conf_desc.stream_type = 0x15;
+
   //we need a Decoder Specific Info descriptor
-  DecoderSpecificInfoDescriptor *desc = desc_dec_specific_info_new();
+  esds->es.dec_conf_desc.dec_specific_info = desc =
+      desc_dec_specific_info_new();
   desc_dec_specific_info_alloc_data(desc, GST_BUFFER_SIZE(codec_data));
-  for(i = 0; i < GST_BUFFER_SIZE(codec_data); i++) {
-    desc->data[i] = GST_BUFFER_DATA(codec_data)[i];
-  }
-  mp4a->es->es.dec_conf_desc.dec_specific_info = desc;
 
+  memcpy (desc->data, GST_BUFFER_DATA (codec_data),
+      GST_BUFFER_SIZE(codec_data));
+ 
+  wave->extension_atoms =
+      atom_info_list_prepend_atom (wave->extension_atoms, (Atom *) esds,
+          (AtomGetSizeFunc) atom_esds_get_size,
+          (AtomCopyDataFunc) atom_esds_copy_data,
+          (AtomFreeFunc) atom_esds_free);
+
+  /* Add FRMA to the WAVE */
+  frma = atom_frma_new();
+  frma->media_type = FOURCC_mp4a;
+
+  wave->extension_atoms =
+      atom_info_list_prepend_atom (wave->extension_atoms, (Atom *) frma,
+          (AtomGetSizeFunc) atom_frma_get_size,
+          (AtomCopyDataFunc) atom_frma_copy_data,
+          (AtomFreeFunc) atom_frma_free);
 }
 
 void atom_trak_set_amrnb(AtomTRAK *trak, AtomsContext *context, guint32 rate, guint32 channels) {
-  AtomMP4A *samr = atom_trak_set_generic_audio(trak, context, FOURCC_samr, rate, channels);
+  SampleTableEntryMP4A *samr = atom_trak_set_generic_audio(trak, context, FOURCC_samr, rate, channels);
   samr->compression_id = 0;
 }
 
 void atom_trak_set_raw_audio(AtomTRAK *trak, AtomsContext *context, guint32 rate,
     guint32 channels) {
-  AtomMP4A *raw = atom_trak_set_generic_audio(trak, context, FOURCC_raw_, rate, channels);
+  SampleTableEntryMP4A *raw = atom_trak_set_generic_audio(trak, context, FOURCC_raw_, rate, channels);
   raw->sample_size = 8;
   atom_trak_set_constant_size_samples(trak, 1);
 }
 
 void atom_trak_set_twos_audio(AtomTRAK *trak, AtomsContext *context, guint32 rate,
     guint32 channels, guint32 depth) {
-  AtomMP4A *twos = atom_trak_set_generic_audio(trak, context, FOURCC_twos, rate, channels);
+  SampleTableEntryMP4A *twos = atom_trak_set_generic_audio(trak, context, FOURCC_twos, rate, channels);
   twos->sample_size = depth;
   twos->version = 1;
 
@@ -2913,7 +3095,7 @@
 
 void atom_trak_set_sowt_audio(AtomTRAK *trak, AtomsContext *context, guint32 rate,
     guint32 channels, guint32 depth) {
-  AtomMP4A *sowt = atom_trak_set_generic_audio(trak, context, FOURCC_sowt, rate, channels);
+  SampleTableEntryMP4A *sowt = atom_trak_set_generic_audio(trak, context, FOURCC_sowt, rate, channels);
   sowt->sample_size = depth;
   sowt->version = 1;
 
@@ -2930,7 +3112,7 @@
 }
 
 void atom_trak_set_alaw_audio(AtomTRAK *trak, AtomsContext *context, guint32 rate, guint32 channels) {
-  AtomMP4A *alaw = atom_trak_set_generic_audio(trak, context, FOURCC_alaw, rate, channels);
+  SampleTableEntryMP4A *alaw = atom_trak_set_generic_audio(trak, context, FOURCC_alaw, rate, channels);
 
   alaw->version = 1;
 
@@ -2941,7 +3123,7 @@
 }
 
 void atom_trak_set_mulaw_audio(AtomTRAK *trak, AtomsContext *context, guint32 rate, guint32 channels) {
-  AtomMP4A *ulaw = atom_trak_set_generic_audio(trak, context, FOURCC_ulaw, rate, channels);
+  SampleTableEntryMP4A *ulaw = atom_trak_set_generic_audio(trak, context, FOURCC_ulaw, rate, channels);
 
   ulaw->version = 1;
   ulaw->sample_size = 16;
@@ -2952,7 +3134,7 @@
 
 void atom_trak_set_raw_rgb(AtomTRAK *trak, AtomsContext *context, guint32 rate, guint32 width, guint32 height, guint16 depth) {
   atom_trak_set_video_commons(trak, context, rate, width, height);
-  AtomMP4V *raw = atom_stsd_add_video_entry(&trak->mdia.minf.stbl.stsd, context, FOURCC_raw_);
+  SampleTableEntryMP4V *raw = atom_stsd_add_video_entry(&trak->mdia.minf.stbl.stsd, context, FOURCC_raw_);
   raw->width = width;
   raw->height = height;
 
@@ -2962,7 +3144,7 @@
 
 void atom_trak_set_raw_2vuY(AtomTRAK *trak, AtomsContext *context, guint32 rate, guint32 width, guint32 height, guint16 depth) {
   atom_trak_set_video_commons(trak, context, rate, width, height);
-  AtomMP4V *vuy = atom_stsd_add_video_entry(&trak->mdia.minf.stbl.stsd, context, FOURCC_2vuy);
+  SampleTableEntryMP4V *vuy = atom_stsd_add_video_entry(&trak->mdia.minf.stbl.stsd, context, FOURCC_2vuy);
 
   vuy->width = width;
   vuy->height = height;
@@ -2973,7 +3155,7 @@
 
 void atom_trak_set_h263(AtomTRAK *trak, AtomsContext *context, guint32 rate, guint32 width, guint32 height) {
   atom_trak_set_video_commons(trak, context, rate, width, height);
-  AtomMP4V *h263 = atom_stsd_add_video_entry(&trak->mdia.minf.stbl.stsd, context, FOURCC_h263);
+  SampleTableEntryMP4V *h263 = atom_stsd_add_video_entry(&trak->mdia.minf.stbl.stsd, context, FOURCC_h263);
 
   h263->width = width;
   h263->height = height;
@@ -2985,7 +3167,7 @@
 
 void atom_trak_set_part(AtomTRAK *trak, AtomsContext *context, guint32 rate, guint32 width, guint32 height, guint32 fourcc) {
   atom_trak_set_video_commons(trak, context, rate, width, height);
-  AtomMP4V *part = atom_stsd_add_video_entry(&trak->mdia.minf.stbl.stsd, context, fourcc);
+  SampleTableEntryMP4V *part = atom_stsd_add_video_entry(&trak->mdia.minf.stbl.stsd, context, fourcc);
 
   part->width = width;
   part->height = height;
@@ -2995,11 +3177,15 @@
   part->color_table_id = -1;
 }
 
-void atom_trak_set_h264(AtomTRAK *trak, AtomsContext *context, guint32 rate, guint32 width,
-    guint32 height, const GstBuffer* codec_data) {
+void
+atom_trak_set_h264(AtomTRAK *trak, AtomsContext *context, guint32 rate,
+    guint32 width, guint32 height, const GstBuffer* codec_data) {
+  SampleTableEntryMP4V *h264;
+
   atom_trak_set_video_commons(trak, context, rate, width, height);
-  AtomMP4V *h264 = atom_stsd_add_video_entry(&trak->mdia.minf.stbl.stsd, context, FOURCC_avc1);
 
+  h264 = atom_stsd_add_video_entry(&trak->mdia.minf.stbl.stsd, context, FOURCC_avc1);
+
   h264->width = width;
   h264->height = height;
 
@@ -3008,8 +3194,9 @@
   h264->color_table_id = -1;
 
   AtomData *data = atom_data_new_from_gst_buffer(FOURCC_avcC, codec_data);
-  atom_mp4v_add_extra_atom(h264, (Atom*)data,
-      (AtomGetSizeFunc)atom_data_get_size,
+  
+  h264->extra_atoms = atom_info_list_prepend_atom (h264->extra_atoms,
+      (Atom*)data, (AtomGetSizeFunc)atom_data_get_size,
       (AtomCopyDataFunc)atom_data_copy_data,
       (AtomFreeFunc)atom_data_free);
 }
Index: src/fourcc.h
===================================================================
--- src/fourcc.h	(revision 122)
+++ src/fourcc.h	(working copy)
@@ -24,6 +24,8 @@
 
 G_BEGIN_DECLS
 
+#define FOURCC_null     0x0
+
 #define FOURCC_moov     GST_MAKE_FOURCC('m','o','o','v')
 #define FOURCC_mvhd     GST_MAKE_FOURCC('m','v','h','d')
 #define FOURCC_iods	GST_MAKE_FOURCC('i','o','d','s')
Index: src/atoms.h
===================================================================
--- src/atoms.h	(revision 122)
+++ src/atoms.h	(working copy)
@@ -59,21 +59,24 @@
 typedef struct _AtomSTTS AtomSTTS;
 typedef struct _AtomSTSS AtomSTSS;
 typedef struct _AtomESDS AtomESDS;
+typedef struct _AtomFRMA AtomFRMA;
 typedef struct _AtomSTSD AtomSTSD;
 typedef struct _AtomSTSZ AtomSTSZ;
 typedef struct _AtomSTSC AtomSTSC;
 typedef struct _AtomSTCO64 AtomSTCO64;
 typedef struct _AtomCTTS AtomCTTS;
-typedef struct _AtomMP4A AtomMP4A;
+typedef struct _AtomWAVE AtomWAVE;
+
+typedef struct _SampleTableEntryMP4A SampleTableEntryMP4A;
 typedef struct _AtomHintSampleEntry AtomHintSampleEntry;
-typedef struct _AtomMP4V AtomMP4V;
-typedef struct _AtomMP4S AtomMP4S;
+typedef struct _SampleTableEntryMP4V SampleTableEntryMP4V;
+typedef struct _SampleTableEntryMP4S SampleTableEntryMP4S;
 
 typedef struct _CTTSEntry CTTSEntry;
 typedef struct _STTSEntry STTSEntry;
 typedef struct _STSDEntry STSDEntry;
 typedef struct _STSCEntry STSCEntry;
-typedef struct _AtomSampleEntry AtomSampleEntry;
+typedef struct _SampleTableEntry SampleTableEntry;
 
 /* functions */
 
@@ -299,13 +302,18 @@
   ESDescriptor es;
 };
 
+struct _AtomFRMA {
+  Atom header;
+  guint32 media_type;
+};
+
 enum SampleEntryKind {
   UNKNOWN,
   AUDIO,
   VIDEO
 };
 
-struct _AtomSampleEntry {
+struct _SampleTableEntry {
   Atom header;
 
   guint8 reserved[6]; // = 0
@@ -317,13 +325,13 @@
 };
 
 struct _AtomHintSampleEntry {
-  AtomSampleEntry se;
+  SampleTableEntry se;
   guint32 size;
   guint8 *data;
 };
 
-struct _AtomMP4V {
-  AtomSampleEntry se;
+struct _SampleTableEntryMP4V {
+  SampleTableEntry se;
 
   guint16 version;
   guint16 revision_level; //0
@@ -351,8 +359,8 @@
 //  AtomESD es;
 };
 
-struct _AtomMP4A {
-  AtomSampleEntry se;
+struct _SampleTableEntryMP4A {
+  SampleTableEntry se;
 
   guint16 version;
   guint16 revision_level;
@@ -371,11 +379,11 @@
   guint32 bytes_per_sample;
 
   //we don't need this always, so when NULL -> not needed
-  AtomESDS *es;
+  GList *extension_atoms;
 };
 
-struct _AtomMP4S {
-  AtomSampleEntry se;
+struct _SampleTableEntryMP4S {
+  SampleTableEntry se;
 
   AtomESDS es;
 };
@@ -383,7 +391,7 @@
 struct _AtomSTSD {
   AtomFull header;
 
-  GList *entries; //list of subclasses of AtomSampleEntry
+  GList *entries; //list of subclasses of SampleTableEntry
 };
 
 struct _AtomSTSZ {
@@ -514,6 +522,12 @@
   AtomUDTA *udta;
 };
 
+struct _AtomWAVE {
+  Atom header;
+
+  GList *extension_atoms; /* List of AtomInfo */
+};
+
 /* ----- FUNCTIONS ------ */
 
 guint64 atom_copy_data(Atom *atom, guint8 *buffer, guint64 size, guint64* offset);
Index: autoregen.sh
===================================================================
--- autoregen.sh	(revision 122)
+++ autoregen.sh	(working copy)
@@ -1,2 +1,2 @@
 #!/bin/sh
-./autogen.sh --prefix=/usr $@
+./autogen.sh  $@
