Coverage Report - org.jaudiotagger.tag.mp4.Mp4TagCreator
 
Classes in this File Line Coverage Branch Coverage Complexity
Mp4TagCreator
87%
27/31
100%
8/8
10
 
 1  
 /*
 2  
  * Entagged Audio Tag library
 3  
  * Copyright (c) 2003-2005 RaphaĆ«l Slinckx <raphael@slinckx.net>
 4  
  * 
 5  
  * This library is free software; you can redistribute it and/or
 6  
  * modify it under the terms of the GNU Lesser General Public
 7  
  * License as published by the Free Software Foundation; either
 8  
  * version 2.1 of the License, or (at your option) any later version.
 9  
  *  
 10  
  * This library is distributed in the hope that it will be useful,
 11  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
  * Lesser General Public License for more details.
 14  
  * 
 15  
  * You should have received a copy of the GNU Lesser General Public
 16  
  * License along with this library; if not, write to the Free Software
 17  
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 18  
  */
 19  
 package org.jaudiotagger.tag.mp4;
 20  
 
 21  
 import org.jaudiotagger.audio.generic.AbstractTagCreator;
 22  
 import org.jaudiotagger.audio.generic.Utils;
 23  
 import org.jaudiotagger.audio.mp4.Mp4NotMetaFieldKey;
 24  
 import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader;
 25  
 import org.jaudiotagger.tag.FieldKey;
 26  
 import org.jaudiotagger.tag.KeyNotFoundException;
 27  
 import org.jaudiotagger.tag.Tag;
 28  
 import org.jaudiotagger.tag.TagField;
 29  
 import org.jaudiotagger.tag.mp4.field.Mp4TagCoverField;
 30  
 
 31  
 import java.io.ByteArrayOutputStream;
 32  
 import java.io.IOException;
 33  
 import java.io.UnsupportedEncodingException;
 34  
 import java.nio.ByteBuffer;
 35  
 import java.util.Iterator;
 36  
 
 37  
 /**
 38  
  * Create raw content of mp4 tag data, concerns itself with atoms upto the ilst atom
 39  
  * <p/>
 40  
  * <p>This level is was selected because the ilst atom can be recreated without reference to existing mp4 fields
 41  
  * but fields above this level are dependent upon other information that is not held in the tag.
 42  
  * <p/>
 43  
  * <pre>
 44  
  * |--- ftyp
 45  
  * |--- moov
 46  
  * |......|
 47  
  * |......|----- mvdh
 48  
  * |......|----- trak
 49  
  * |......|----- udta
 50  
  * |..............|
 51  
  * |..............|-- meta
 52  
  * |....................|
 53  
  * |....................|-- hdlr
 54  
  * |....................|-- ilst
 55  
  * |....................|.. ..|
 56  
  * |....................|.....|---- @nam (Optional for each metadatafield)
 57  
  * |....................|.....|.......|-- data
 58  
  * |....................|.....|....... ecetera
 59  
  * |....................|.....|---- ---- (Optional for reverse dns field)
 60  
  * |....................|.............|-- mean
 61  
  * |....................|.............|-- name
 62  
  * |....................|.............|-- data
 63  
  * |....................|................ ecetere
 64  
  * |....................|-- free
 65  
  * |--- free
 66  
  * |--- mdat
 67  
  * </pre>
 68  
  */
 69  16
 public class Mp4TagCreator extends AbstractTagCreator
 70  
 {
 71  
     /**
 72  
      * Convert tagdata to rawdata ready for writing to file
 73  
      *
 74  
      * @param tag
 75  
      * @param padding TODO padding parameter currently ignored
 76  
      * @return
 77  
      * @throws UnsupportedEncodingException
 78  
      */
 79  
     public ByteBuffer convert(Tag tag, int padding) throws UnsupportedEncodingException
 80  
     {
 81  
         try
 82  
         {
 83  
             //Add metadata raw content
 84  183
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
 85  183
             Iterator<TagField> it = tag.getFields();
 86  183
             boolean processedArtwork = false;
 87  3905
             while (it.hasNext())
 88  
             {
 89  3722
                 TagField frame = it.next();
 90  
                 //To ensure order is maintained dont process artwork until iterator hits it.
 91  3722
                 if (frame instanceof Mp4TagCoverField)
 92  
                 {
 93  124
                     if (processedArtwork)
 94  
                     {
 95  
                         //ignore
 96  
                     }
 97  
                     else
 98  
                     {
 99  85
                         processedArtwork = true;
 100  
 
 101  
                         //Because each artwork image is held within the tag as a seperate field, but when
 102  
                         //they are written they are all held under a single covr box we need to do some checks
 103  
                         //and special processing here if we have any artwork image (this code only neccessary
 104  
                         //if we have more than 1 but do it anyway even if only have 1 image)
 105  85
                         ByteArrayOutputStream covrDataBaos = new ByteArrayOutputStream();
 106  
 
 107  
                         try
 108  
                         {
 109  85
                             for (TagField artwork : tag.getFields(FieldKey.COVER_ART))
 110  
                             {
 111  124
                                 covrDataBaos.write(((Mp4TagField) artwork).getRawContentDataOnly());
 112  
                             }
 113  
                         }
 114  0
                         catch (KeyNotFoundException knfe)
 115  
                         {
 116  
                             //This cannot happen
 117  0
                             throw new RuntimeException("Unable to find COVERART Key");
 118  85
                         }
 119  
 
 120  
                         //Now create the parent Data
 121  85
                         byte[] data = covrDataBaos.toByteArray();
 122  85
                         baos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + data.length));
 123  85
                         baos.write(Utils.getDefaultBytes(Mp4FieldKey.ARTWORK.getFieldName(), "ISO-8859-1"));
 124  85
                         baos.write(data);
 125  85
                     }
 126  
                 }
 127  
                 else
 128  
                 {                     
 129  3598
                     baos.write(frame.getRawContent());
 130  
                 }
 131  3722
             }
 132  
 
 133  
             //Wrap into ilst box
 134  183
             ByteArrayOutputStream ilst = new ByteArrayOutputStream();
 135  183
             ilst.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + baos.size()));
 136  183
             ilst.write(Utils.getDefaultBytes(Mp4NotMetaFieldKey.ILST.getFieldName(), "ISO-8859-1"));
 137  183
             ilst.write(baos.toByteArray());
 138  
 
 139  
             //Put into ByteBuffer
 140  183
             ByteBuffer buf = ByteBuffer.wrap(ilst.toByteArray());
 141  183
             buf.rewind();
 142  183
             return buf;
 143  
         }
 144  0
         catch (IOException ioe)
 145  
         {
 146  
             //Should never happen as not writing to file at this point
 147  0
             throw new RuntimeException(ioe);
 148  
         }
 149  
     }
 150  
 }