public int WriteToByteArray(Byte[] dest, int offset) { bool isRoot = this.AtomCode == null; // このnodeListがルートかどうか int bodyLen = WriteBodyToByteArray(dest, offset + (isRoot ? 0 : 8)); if (!isRoot) { MP4.UIn32ToBE((UInt32)(bodyLen + 8), dest, offset); dest[offset + 4] = AtomCode[0]; dest[offset + 5] = AtomCode[1]; dest[offset + 6] = AtomCode[2]; dest[offset + 7] = AtomCode[3]; } return bodyLen + (isRoot ? 0 : 8); }
private bool FixMoraMP4(string filepath) { if (!File.Exists(filepath)) { return(false); } var destfilepath = (System.IO.Path.GetExtension(filepath).ToLower() == ".m4a") ? filepath + ".m4a" : System.IO.Path.ChangeExtension(filepath, ".m4a"); using (var fs = System.IO.File.OpenRead(filepath)) { try { // 元のファイルサイズを保持 var originalsize = fs.Length; // mp4の読み出し var mp4 = MP4.Read(fs, true); // トラック名を表示 var title = getTagText <MP4.ATOM__nam>(mp4); var artist = getTagText <MP4.ATOM__ART>(mp4); AppendLog(String.Format(" {0} - {1}", title ?? "?", artist ?? "?")); // brandを修正 mp4.GetChildNode <MP4.ATOM_ftyp>().brands = M4A_FTYP_BRANDS; // id32を探す var id32atom = mp4.GetChildNode <MP4.ATOM_ID32>(); if (id32atom != null) { var id32body = new byte[id32atom.data.Length - 6]; System.Buffer.BlockCopy(id32atom.data, 6, id32body, 0, id32atom.data.Length - 6); ID3V2Tag.id3tag id3tag = null; try { id3tag = ID3V2Tag.read_id3tag(new MemoryStream(id32body), false); } catch { AppendLog("ID32領域の内容が読めませんでした。が処理を続行します。"); } // ID3から使えるデータを引っこ抜く if (id3tag != null) { CopyID32DataToMP4(id3tag, mp4); } // ID32の親から、hdlrとID32を削除する var parent = id32atom.ParentNode; parent.RemoveChild(parent.GetChildNode <MP4.ATOM_hdlr>()); parent.RemoveChild(id32atom); // ID32の入っていたmetaが空になっているなら、それも削除 if (parent.GetChildNodes <MP4.ATOM>().Count() == 0) { parent.ParentNode.RemoveChild(parent); } } using (var fsw = System.IO.File.OpenWrite(destfilepath)) { var buf = new byte[fs.Length + M4A_FTYP_BRANDS.Length]; // 一旦編集後のmp4をバッファに書き出してみる var len = mp4.WriteToByteArray(buf, 0); // stco atomのシークテーブルを補正 var stcos = mp4.GetChildNodes <MP4.ATOM_stco>(); foreach (var stco in stcos) { stco.Adjust((int)(len - originalsize)); } // mp4を生成しなおしてファイルに書く len = mp4.WriteToByteArray(buf, 0); fsw.Write(buf, 0, len); } } catch (Exception ex) { AppendLog(ex.StackTrace); return(false); } } return(true); }