FFMpegでID3タグが文字化けるのを直すパッチを作った

forked-daapdで文字化けしてるから、それを直したい。
とりあえず文字化けの原因は潰したから今度試す。
 
パッチの前にちょっと解説。
 

なぜ文字化けるのか

ID3v2が対応している文字コードは、
ID3v2.2〜ID3v2.3の場合、ISO-8859-1とUTF-16だけ。
ID3v2.4の場合、ISO-8859-1とUTF-16UTF-8だけ。
 
どのバージョンを使ってもShiftJISは対応していない。
それなのに日本語をISO-8859-1としてShiftJISを突っ込んでしまっているらしい。
システムでShiftJISを使っているWindowsでは特に問題にはならないけど、UTF-8を使うLinuxとかだと化ける、という事らしい。
 

改善策

本来ならMP3ファイルのID3タグをUTF-16ないしUTF-8へ変換するべき。
でもID3タグを変換するのは面倒だから、FFMpeg側で対応する。
ISO-8859-1だった場合にShiftJISからUTF-8への変換をするようにした。
FFMpegに非はないのに…。)
 

FFMpegのShiftJIS対応パッチ

元のソース / バージョンは以下の通り
git: git://source.ffmpeg.org/ffmpeg.git
commit: ee0cab7721cc31e5d8027ec7df6c3ebd60ea50b5

--- libavformat/id3v2.c.org	2012-01-27 02:42:00.787551422 +0900
+++ libavformat/id3v2.c	2012-01-27 05:36:12.833550837 +0900
@@ -38,6 +38,7 @@
 #include "libavutil/intreadwrite.h"
 #include "libavutil/dict.h"
 #include "avio_internal.h"
+#include <iconv.h>
 
 const AVMetadataConv ff_id3v2_34_metadata_conv[] = {
     { "TALB", "album"},
@@ -167,6 +168,12 @@
     unsigned int (*get)(AVIOContext*) = avio_rb16;
     AVIOContext *dynbuf;
 
+    iconv_t ic;
+    char *sjis, *p_sjis;
+    size_t sjis_size;
+    char *utf8, *p_utf8;
+    size_t utf8_size;
+
     if ((ret = avio_open_dyn_buf(&dynbuf)) < 0) {
         av_log(s, AV_LOG_ERROR, "Error opening memory stream\n");
         return ret;
@@ -175,11 +182,39 @@
     switch (encoding) {
 
     case ID3v2_ENCODING_ISO8859:
+/*
         while (left && ch) {
             ch = avio_r8(pb);
             PUT_UTF8(ch, tmp, avio_w8(dynbuf, tmp);)
             left--;
         }
+*/
+
+        // iconv in
+        sjis_size = left;
+        sjis = p_sjis = av_malloc(sjis_size);
+        avio_read(pb, sjis, sjis_size);
+
+        // iconv out
+        utf8_size = sjis_size * 3;
+        utf8 = p_utf8 = av_malloc(utf8_size);
+
+        // iconv
+        ic = iconv_open("UTF-8", "SJIS");
+        iconv(ic, &p_sjis, &sjis_size, &p_utf8, &utf8_size);
+        if (utf8==p_utf8 || *(p_utf8-1)) {
+            *(p_utf8++) = 0;
+        }
+        //av_log(s, AV_LOG_INFO, "iconv convert: %s\n", utf8);
+
+        // copy
+        avio_write(dynbuf, utf8, p_utf8-utf8);
+
+        // iconv release
+        av_free(sjis);
+        av_free(utf8);
+        iconv_close(ic);
+        ch = 0;
         break;
 
     case ID3v2_ENCODING_UTF16BOM:

 

msysでコンパイル

iconvがリンクされてない場合はconfigureで以下パラメータをつける。

--extra-libs=-liconv

 

参考URL

ID3 - Wikipedia, the free encyclopedia
http://en.wikipedia.org/wiki/ID3#ID3v2