Merge pull request #5039 from CEikermann/patch-1
[vuplus_xbmc] / xbmc / cdrip / EncoderLame.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program 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
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "EncoderLame.h"
22 #include "settings/Settings.h"
23 #include "utils/log.h"
24
25 #ifdef TARGET_WINDOWS
26 extern "C" FILE *fopen_utf8(const char *_Filename, const char *_Mode);
27 #else
28 #define fopen_utf8 fopen
29 #endif
30
31 CEncoderLame::CEncoderLame()
32 {
33   memset(m_inPath, 0, 1024 + 1);
34   memset(m_outPath, 0, 1024 + 1);
35 }
36
37 bool CEncoderLame::Init(const char* strFile, int iInChannels, int iInRate, int iInBits)
38 {
39   // we only accept 2 / 44100 / 16 atm
40   if (iInChannels != 2 || iInRate != 44100 || iInBits != 16) return false;
41
42   // set input stream information and open the file
43   if (!CEncoder::Init(strFile, iInChannels, iInRate, iInBits)) return false;
44
45   // load the lame dll
46   if (!m_dll.Load())
47     return false;
48
49   m_pGlobalFlags = m_dll.lame_init();
50   if (!m_pGlobalFlags)
51   {
52     CLog::Log(LOGERROR, "Error: lame_init() failed");
53     return false;
54   }
55
56   // setup parmaters, see lame.h for possibilities
57   if (CSettings::Get().GetInt("audiocds.quality") == CDDARIP_QUALITY_CBR)
58   {
59     int bitrate = CSettings::Get().GetInt("audiocds.bitrate");
60     // use cbr and specified bitrate from settings
61     CLog::Log(LOGDEBUG, "Lame setting CBR bitrate %d", bitrate);
62     m_dll.lame_set_brate(m_pGlobalFlags, bitrate);
63   }
64   else
65   {
66     // use presets (VBR)
67     int preset;
68     switch (CSettings::Get().GetInt("audiocds.quality"))
69     {
70     case CDDARIP_QUALITY_MEDIUM:
71       preset = MEDIUM;
72       break;
73     case CDDARIP_QUALITY_STANDARD:
74       preset = STANDARD;
75       break;
76     case CDDARIP_QUALITY_EXTREME:
77       preset = EXTREME;
78       break;
79     default:
80       preset = STANDARD;
81     }
82     CLog::Log(LOGDEBUG, "Lame setting preset %d", preset);
83     m_dll.lame_set_preset(m_pGlobalFlags, preset);
84   }
85
86   m_dll.lame_set_asm_optimizations(m_pGlobalFlags, MMX, 1);
87   m_dll.lame_set_asm_optimizations(m_pGlobalFlags, SSE, 1);
88   m_dll.lame_set_in_samplerate(m_pGlobalFlags, 44100);
89
90   // Setup the ID3 tagger
91   m_dll.id3tag_init(m_pGlobalFlags);
92   m_dll.id3tag_add_v2(m_pGlobalFlags);
93   m_dll.id3tag_set_title(m_pGlobalFlags, m_strTitle.c_str());
94   m_dll.id3tag_set_artist(m_pGlobalFlags, m_strArtist.c_str());
95   m_dll.id3tag_set_textinfo_latin1(m_pGlobalFlags, "TPE2", m_strAlbumArtist.c_str());
96   m_dll.id3tag_set_album(m_pGlobalFlags, m_strAlbum.c_str());
97   m_dll.id3tag_set_year(m_pGlobalFlags, m_strYear.c_str());
98   m_dll.id3tag_set_track(m_pGlobalFlags, m_strTrack.c_str());
99   int test = m_dll.id3tag_set_genre(m_pGlobalFlags, m_strGenre.c_str());
100   if(test==-1)
101     m_dll.id3tag_set_genre(m_pGlobalFlags,"Other");
102
103   // Now that all the options are set, lame needs to analyze them and
104   // set some more internal options and check for problems
105   if (m_dll.lame_init_params(m_pGlobalFlags) < 0)
106   {
107     CLog::Log(LOGERROR, "Error: Cannot init Lame params");
108     return false;
109   }
110
111   return true;
112 }
113
114 int CEncoderLame::Encode(int nNumBytesRead, BYTE* pbtStream)
115 {
116   int iBytes = m_dll.lame_encode_buffer_interleaved(m_pGlobalFlags, (short*)pbtStream, nNumBytesRead / 4, m_buffer, sizeof(m_buffer));
117
118   if (iBytes < 0)
119   {
120     CLog::Log(LOGERROR, "Internal Lame error: %i", iBytes);
121     return 0;
122   }
123
124   if (WriteStream(m_buffer, iBytes) != iBytes)
125   {
126     CLog::Log(LOGERROR, "Error writing Lame buffer to file");
127     return 0;
128   }
129
130   return 1;
131 }
132
133 bool CEncoderLame::Close()
134 {
135   // may return one more mp3 frames
136   int iBytes = m_dll.lame_encode_flush(m_pGlobalFlags, m_buffer, sizeof(m_buffer));
137
138   if (iBytes < 0)
139   {
140     CLog::Log(LOGERROR, "Internal Lame error: %i", iBytes);
141     return false;
142   }
143
144   WriteStream(m_buffer, iBytes);
145   FlushStream();
146   FileClose();
147
148   // open again, but now the old way, lame only accepts FILE pointers
149   FILE* file = fopen_utf8(m_strFile.c_str(), "rb+");
150   if (!file)
151   {
152     CLog::Log(LOGERROR, "Error: Cannot open file for writing tags: %s", m_strFile.c_str());
153     return false;
154   }
155
156   m_dll.lame_mp3_tags_fid(m_pGlobalFlags, file); /* add VBR tags to mp3 file */
157   fclose(file);
158
159   m_dll.lame_close(m_pGlobalFlags);
160
161   // unload the lame dll
162   m_dll.Unload();
163
164
165
166   return true;
167 }