diff options
-rw-r--r-- | language/English/strings.xml | 2 | ||||
-rw-r--r-- | project/VS2008Express/XBMC.vcproj | 12 | ||||
-rw-r--r-- | project/VS2010Express/XBMC.vcxproj | 3 | ||||
-rw-r--r-- | xbmc/GUISettings.cpp | 2 | ||||
-rw-r--r-- | xbmc/GUISettings.h | 1 | ||||
-rw-r--r-- | xbmc/GUIWindowSettingsCategory.cpp | 13 | ||||
-rw-r--r-- | xbmc/cdrip/DllFlacEnc.h | 100 | ||||
-rw-r--r-- | xbmc/cdrip/EncoderFlac.cpp | 193 | ||||
-rw-r--r-- | xbmc/cdrip/EncoderFlac.h | 50 | ||||
-rw-r--r-- | xbmc/cdrip/Makefile.in | 1 |
10 files changed, 374 insertions, 3 deletions
diff --git a/language/English/strings.xml b/language/English/strings.xml index d234324e09..20f68d57b0 100644 --- a/language/English/strings.xml +++ b/language/English/strings.xml @@ -580,6 +580,7 @@ <string id="662">This file is no longer available.</string> <string id="663">Would you like to remove it from the library?</string> <string id="664">Browse for Script</string> + <string id="665">Compression level</string> <string id="700">Cleaning up library</string> <string id="701">Removing old songs from the library</string> @@ -2265,6 +2266,7 @@ <string id="34002">Wav</string> <string id="34003">DXVA2</string> <string id="34004">VAAPI</string> + <string id="34005">Flac</string> <string id="34100">Speaker Configuration</string> <string id="34101">2.0</string> diff --git a/project/VS2008Express/XBMC.vcproj b/project/VS2008Express/XBMC.vcproj index 5760003959..b38157b761 100644 --- a/project/VS2008Express/XBMC.vcproj +++ b/project/VS2008Express/XBMC.vcproj @@ -6784,6 +6784,10 @@ > </File> <File + RelativePath="..\..\xbmc\cdrip\DllFlacEnc.h" + > + </File> + <File RelativePath="..\..\xbmc\cdrip\DllLameenc.h" > </File> @@ -6808,6 +6812,14 @@ > </File> <File + RelativePath="..\..\xbmc\cdrip\EncoderFlac.cpp" + > + </File> + <File + RelativePath="..\..\xbmc\cdrip\EncoderFlac.h" + > + </File> + <File RelativePath="..\..\xbmc\cdrip\EncoderLame.cpp" > </File> diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj index 06ff852ef2..5a43884d1c 100644 --- a/project/VS2010Express/XBMC.vcxproj +++ b/project/VS2010Express/XBMC.vcxproj @@ -984,6 +984,7 @@ <ClCompile Include="..\..\xbmc\cdrip\CDDAReader.cpp" />
<ClCompile Include="..\..\xbmc\cdrip\CDDARipper.cpp" />
<ClCompile Include="..\..\xbmc\cdrip\Encoder.cpp" />
+ <ClCompile Include="..\..\xbmc\cdrip\EncoderFlac.cpp" />
<ClCompile Include="..\..\xbmc\cdrip\EncoderLame.cpp" />
<ClCompile Include="..\..\xbmc\cdrip\EncoderVorbis.cpp" />
<ClCompile Include="..\..\xbmc\cdrip\EncoderWav.cpp" />
@@ -1767,10 +1768,12 @@ <ClInclude Include="..\..\xbmc\cdrip\CDDAReader.h" />
<ClInclude Include="..\..\xbmc\cdrip\CDDARipper.h" />
<ClInclude Include="..\..\xbmc\cdrip\DllLameenc.h" />
+ <ClInclude Include="..\..\xbmc\cdrip\DllFlacEnc.h" />
<ClInclude Include="..\..\xbmc\cdrip\DllOgg.h" />
<ClInclude Include="..\..\xbmc\cdrip\DllVorbis.h" />
<ClInclude Include="..\..\xbmc\cdrip\DllVorbisEnc.h" />
<ClInclude Include="..\..\xbmc\cdrip\Encoder.h" />
+ <ClInclude Include="..\..\xbmc\cdrip\EncoderFlac.h" />
<ClInclude Include="..\..\xbmc\cdrip\EncoderLame.h" />
<ClInclude Include="..\..\xbmc\cdrip\EncoderVorbis.h" />
<ClInclude Include="..\..\xbmc\cdrip\EncoderWav.h" />
diff --git a/xbmc/GUISettings.cpp b/xbmc/GUISettings.cpp index 20800b9524..7029c6c3b7 100644 --- a/xbmc/GUISettings.cpp +++ b/xbmc/GUISettings.cpp @@ -356,6 +356,7 @@ void CGUISettings::Initialize() encoders.insert(make_pair(34000,CDDARIP_ENCODER_LAME)); encoders.insert(make_pair(34001,CDDARIP_ENCODER_VORBIS)); encoders.insert(make_pair(34002,CDDARIP_ENCODER_WAV)); + encoders.insert(make_pair(34005,CDDARIP_ENCODER_FLAC)); AddInt(acd, "audiocds.encoder", 621, CDDARIP_ENCODER_LAME, encoders, SPIN_CONTROL_TEXT); map<int,int> qualities; @@ -365,6 +366,7 @@ void CGUISettings::Initialize() qualities.insert(make_pair(603,CDDARIP_QUALITY_EXTREME)); AddInt(acd, "audiocds.quality", 622, CDDARIP_QUALITY_CBR, qualities, SPIN_CONTROL_TEXT); AddInt(acd, "audiocds.bitrate", 623, 192, 128, 32, 320, SPIN_CONTROL_INT_PLUS, MASK_KBPS); + AddInt(acd, "audiocds.compressionlevel", 665, 5, 0, 1, 8, SPIN_CONTROL_INT_PLUS); #ifdef HAS_KARAOKE CSettingsCategory* kar = AddCategory(3, "karaoke", 13327); diff --git a/xbmc/GUISettings.h b/xbmc/GUISettings.h index 7e30aeef0e..bacf33fdc9 100644 --- a/xbmc/GUISettings.h +++ b/xbmc/GUISettings.h @@ -66,6 +66,7 @@ class TiXmlElement; #define CDDARIP_ENCODER_LAME 0 #define CDDARIP_ENCODER_VORBIS 1 #define CDDARIP_ENCODER_WAV 2 +#define CDDARIP_ENCODER_FLAC 3 #define CDDARIP_QUALITY_CBR 0 #define CDDARIP_QUALITY_MEDIUM 1 diff --git a/xbmc/GUIWindowSettingsCategory.cpp b/xbmc/GUIWindowSettingsCategory.cpp index 513fd9a0aa..86ed614144 100644 --- a/xbmc/GUIWindowSettingsCategory.cpp +++ b/xbmc/GUIWindowSettingsCategory.cpp @@ -744,13 +744,20 @@ void CGUIWindowSettingsCategory::UpdateSettings() else if (strSetting.Equals("audiocds.quality")) { // only visible if we are doing non-WAV ripping CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(g_guiSettings.GetInt("audiocds.encoder") != CDDARIP_ENCODER_WAV); + if (pControl) pControl->SetEnabled(g_guiSettings.GetInt("audiocds.encoder") != CDDARIP_ENCODER_WAV && + g_guiSettings.GetInt("audiocds.encoder") != CDDARIP_ENCODER_FLAC); } else if (strSetting.Equals("audiocds.bitrate")) { // only visible if we are ripping to CBR CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled((g_guiSettings.GetInt("audiocds.encoder") != CDDARIP_ENCODER_WAV) && - (g_guiSettings.GetInt("audiocds.quality") == CDDARIP_QUALITY_CBR)); + if (pControl) pControl->SetEnabled(g_guiSettings.GetInt("audiocds.encoder") != CDDARIP_ENCODER_WAV && + g_guiSettings.GetInt("audiocds.encoder") != CDDARIP_ENCODER_FLAC && + g_guiSettings.GetInt("audiocds.quality") == CDDARIP_QUALITY_CBR); + } + else if (strSetting.Equals("audiocds.compressionlevel")) + { // only visible if we are doing FLAC ripping + CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); + if (pControl) pControl->SetEnabled(g_guiSettings.GetInt("audiocds.encoder") == CDDARIP_ENCODER_FLAC); } else if ( strSetting.Equals("audiooutput.passthroughdevice") || diff --git a/xbmc/cdrip/DllFlacEnc.h b/xbmc/cdrip/DllFlacEnc.h new file mode 100644 index 0000000000..4bdb38d4f3 --- /dev/null +++ b/xbmc/cdrip/DllFlacEnc.h @@ -0,0 +1,100 @@ +#pragma once
+
+/*
+ * Copyright (C) 2005-2008 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#if (defined HAVE_CONFIG_H) && (!defined WIN32)
+ #include "config.h"
+#endif
+#if defined(_LINUX) && !defined(__APPLE__)
+ #include <FLAC/stream_encoder.h>
+ #include <FLAC/metadata.h>
+#else
+ #include "../cores/paplayer/FLACCodec/flac-1.2.1/include/FLAC/stream_encoder.h"
+ #include "../cores/paplayer/FLACCodec/flac-1.2.1/include/FLAC/metadata.h"
+#endif
+
+#include "DynamicDll.h"
+
+class DllFlacEncInterface
+{
+public:
+ virtual FLAC__StreamEncoder *FLAC__stream_encoder_new()=0;
+ virtual FLAC__bool FLAC__stream_encoder_set_verify(FLAC__StreamEncoder *encoder, FLAC__bool value)=0;
+ virtual FLAC__bool FLAC__stream_encoder_set_compression_level(FLAC__StreamEncoder *encoder, unsigned value)=0;
+ virtual FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encoder, unsigned value)=0;
+ virtual FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder *encoder, unsigned value)=0;
+ virtual FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *encoder, unsigned value)=0;
+ virtual FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__StreamEncoder *encoder, FLAC__uint64 value)=0;
+ virtual FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)=0;
+ virtual FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_stream(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderWriteCallback write_callback, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderTellCallback tell_callback, FLAC__StreamEncoderMetadataCallback metadata_callback, void *client_data)=0;
+ virtual FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)=0;
+ virtual FLAC__StreamEncoderState FLAC__stream_encoder_get_state(FLAC__StreamEncoder *encoder)=0;
+ virtual FLAC__bool FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder)=0;
+ virtual void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder)=0;
+ virtual FLAC__StreamMetadata *FLAC__metadata_object_new(FLAC__MetadataType type)=0;
+ virtual FLAC__bool FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(FLAC__StreamMetadata_VorbisComment_Entry *entry, const char *field_name, const char *field_value)=0;
+ virtual FLAC__bool FLAC__metadata_object_vorbiscomment_append_comment(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy)=0;
+ virtual void FLAC__metadata_object_delete(FLAC__StreamMetadata *object)=0;
+ virtual ~DllFlacEncInterface() {}
+};
+
+class DllFlacEnc : public DllDynamic, DllFlacEncInterface
+{
+ DECLARE_DLL_WRAPPER(DllFlacEnc, DLL_PATH_FLAC_CODEC)
+ DEFINE_METHOD0(FLAC__StreamEncoder*, FLAC__stream_encoder_new)
+ DEFINE_METHOD2(FLAC__bool, FLAC__stream_encoder_set_verify, (FLAC__StreamEncoder *p1, FLAC__bool p2))
+ DEFINE_METHOD2(FLAC__bool, FLAC__stream_encoder_set_compression_level, (FLAC__StreamEncoder *p1, unsigned p2))
+ DEFINE_METHOD2(FLAC__bool, FLAC__stream_encoder_set_channels, (FLAC__StreamEncoder *p1, unsigned p2))
+ DEFINE_METHOD2(FLAC__bool, FLAC__stream_encoder_set_bits_per_sample, (FLAC__StreamEncoder *p1, unsigned p2))
+ DEFINE_METHOD2(FLAC__bool, FLAC__stream_encoder_set_sample_rate, (FLAC__StreamEncoder *p1, unsigned p2))
+ DEFINE_METHOD2(FLAC__bool, FLAC__stream_encoder_set_total_samples_estimate, (FLAC__StreamEncoder *p1, FLAC__uint64 p2))
+ DEFINE_METHOD3(FLAC__bool, FLAC__stream_encoder_set_metadata, (FLAC__StreamEncoder *p1, FLAC__StreamMetadata **p2, unsigned p3))
+ DEFINE_METHOD6(FLAC__StreamEncoderInitStatus, FLAC__stream_encoder_init_stream, (FLAC__StreamEncoder *p1, FLAC__StreamEncoderWriteCallback p2, FLAC__StreamEncoderSeekCallback p3, FLAC__StreamEncoderTellCallback p4, FLAC__StreamEncoderMetadataCallback p5, void *p6))
+ DEFINE_METHOD3(FLAC__bool, FLAC__stream_encoder_process_interleaved, (FLAC__StreamEncoder *p1, const FLAC__int32 p2[], unsigned p3))
+ DEFINE_METHOD1(FLAC__StreamEncoderState, FLAC__stream_encoder_get_state, (FLAC__StreamEncoder *p1))
+ DEFINE_METHOD1(FLAC__bool, FLAC__stream_encoder_finish, (FLAC__StreamEncoder *p1))
+ DEFINE_METHOD1(void, FLAC__stream_encoder_delete, (FLAC__StreamEncoder *p1))
+ DEFINE_METHOD1(FLAC__StreamMetadata *, FLAC__metadata_object_new, (FLAC__MetadataType p1))
+ DEFINE_METHOD3(FLAC__bool, FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair, (FLAC__StreamMetadata_VorbisComment_Entry *p1, const char *p2, const char *p3))
+ DEFINE_METHOD3(FLAC__bool, FLAC__metadata_object_vorbiscomment_append_comment, (FLAC__StreamMetadata *p1, FLAC__StreamMetadata_VorbisComment_Entry p2, FLAC__bool p3))
+ DEFINE_METHOD1(void, FLAC__metadata_object_delete, (FLAC__StreamMetadata *p1))
+
+ BEGIN_METHOD_RESOLVE()
+ RESOLVE_METHOD(FLAC__stream_encoder_new)
+ RESOLVE_METHOD(FLAC__stream_encoder_set_verify)
+ RESOLVE_METHOD(FLAC__stream_encoder_set_compression_level)
+ RESOLVE_METHOD(FLAC__stream_encoder_set_channels)
+ RESOLVE_METHOD(FLAC__stream_encoder_set_bits_per_sample)
+ RESOLVE_METHOD(FLAC__stream_encoder_set_sample_rate)
+ RESOLVE_METHOD(FLAC__stream_encoder_set_total_samples_estimate)
+ RESOLVE_METHOD(FLAC__stream_encoder_set_metadata)
+ RESOLVE_METHOD(FLAC__stream_encoder_init_stream)
+ RESOLVE_METHOD(FLAC__stream_encoder_process_interleaved)
+ RESOLVE_METHOD(FLAC__stream_encoder_get_state)
+ RESOLVE_METHOD(FLAC__stream_encoder_finish)
+ RESOLVE_METHOD(FLAC__stream_encoder_delete)
+ RESOLVE_METHOD(FLAC__metadata_object_new)
+ RESOLVE_METHOD(FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair)
+ RESOLVE_METHOD(FLAC__metadata_object_vorbiscomment_append_comment)
+ RESOLVE_METHOD(FLAC__metadata_object_delete)
+ END_METHOD_RESOLVE()
+};
diff --git a/xbmc/cdrip/EncoderFlac.cpp b/xbmc/cdrip/EncoderFlac.cpp new file mode 100644 index 0000000000..6d4dcb39cb --- /dev/null +++ b/xbmc/cdrip/EncoderFlac.cpp @@ -0,0 +1,193 @@ +/*
+ * Copyright (C) 2005-2008 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "EncoderFlac.h"
+#include "utils/log.h"
+#include "FileSystem/File.h"
+#include "GUISettings.h"
+
+CEncoderFlac::CEncoderFlac() : m_encoder(0), m_samplesBuf(new FLAC__int32[SAMPLES_BUF_SIZE])
+{
+ m_metadata[0] = 0;
+}
+
+CEncoderFlac::~CEncoderFlac()
+{
+ delete [] m_samplesBuf;
+}
+
+bool CEncoderFlac::Init(const char* strFile, int iInChannels, int iInRate, int iInBits)
+{
+ // we only accept 2 / 44100 / 16 atm
+ if (iInChannels != 2 || iInRate != 44100 || iInBits != 16)
+ return false;
+
+ // set input stream information and open the file
+ if (!CEncoder::Init(strFile, iInChannels, iInRate, iInBits))
+ return false;
+
+ // load the flac dll
+ if (!m_dll.Load())
+ return false;
+
+ // allocate libFLAC encoder
+ m_encoder = m_dll.FLAC__stream_encoder_new();
+ if (!m_encoder)
+ {
+ CLog::Log(LOGERROR, "Error: FLAC__stream_encoder_new() failed");
+ return false;
+ }
+
+ FLAC__bool ok = 1;
+
+ ok &= m_dll.FLAC__stream_encoder_set_channels(m_encoder, 2);
+ ok &= m_dll.FLAC__stream_encoder_set_bits_per_sample(m_encoder, 16);
+ ok &= m_dll.FLAC__stream_encoder_set_sample_rate(m_encoder, 44100);
+ ok &= m_dll.FLAC__stream_encoder_set_compression_level(m_encoder, g_guiSettings.GetInt("audiocds.compressionlevel"));
+
+ // now add some metadata
+ FLAC__StreamMetadata_VorbisComment_Entry entry;
+ if (ok)
+ {
+ if (
+ (m_metadata[0] = m_dll.FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) == NULL ||
+ !m_dll.FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "ARTIST", m_strArtist.c_str()) ||
+ !m_dll.FLAC__metadata_object_vorbiscomment_append_comment(m_metadata[0], entry, false) ||
+ !m_dll.FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "ALBUM", m_strAlbum.c_str()) ||
+ !m_dll.FLAC__metadata_object_vorbiscomment_append_comment(m_metadata[0], entry, false) ||
+ !m_dll.FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "TITLE", m_strTitle.c_str()) ||
+ !m_dll.FLAC__metadata_object_vorbiscomment_append_comment(m_metadata[0], entry, false) ||
+ !m_dll.FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "GENRE", m_strGenre.c_str()) ||
+ !m_dll.FLAC__metadata_object_vorbiscomment_append_comment(m_metadata[0], entry, false) ||
+ !m_dll.FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "TRACKNUMBER", m_strTrack.c_str()) ||
+ !m_dll.FLAC__metadata_object_vorbiscomment_append_comment(m_metadata[0], entry, false) ||
+ !m_dll.FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "DATE", m_strYear.c_str()) ||
+ !m_dll.FLAC__metadata_object_vorbiscomment_append_comment(m_metadata[0], entry, false) ||
+ !m_dll.FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "COMMENT", m_strComment.c_str()) ||
+ !m_dll.FLAC__metadata_object_vorbiscomment_append_comment(m_metadata[0], entry, false)
+ )
+ {
+ CLog::Log(LOGERROR, "ERROR: FLAC out of memory or tag error\n");
+ ok = false;
+ }
+ else
+ {
+ ok = m_dll.FLAC__stream_encoder_set_metadata(m_encoder, m_metadata, 1);
+ }
+ }
+
+ // initialize encoder in stream mode
+ if (ok)
+ {
+ FLAC__StreamEncoderInitStatus init_status;
+ init_status = m_dll.FLAC__stream_encoder_init_stream(m_encoder, write_callback, seek_callback, tell_callback, 0, this);
+ if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
+ {
+ CLog::Log(LOGERROR, "FLAC encoder initializing error");
+ ok = false;
+ }
+ }
+
+ if (!ok)
+ {
+ CLog::Log(LOGERROR, "Error: FLAC intialization failed");
+ return false;
+ }
+
+ return true;
+}
+
+int CEncoderFlac::Encode(int nNumBytesRead, BYTE* pbtStream)
+{
+ int nLeftSamples = nNumBytesRead / 2; // each sample takes 2 bytes (16 bits per sample)
+ while (nLeftSamples > 0)
+ {
+ int nSamples = nLeftSamples > SAMPLES_BUF_SIZE ? SAMPLES_BUF_SIZE : nLeftSamples;
+
+ // convert the packed little-endian 16-bit PCM samples into an interleaved FLAC__int32 buffer for libFLAC
+ for (int i = 0; i < nSamples; i++)
+ { // inefficient but simple and works on big- or little-endian machines.
+ m_samplesBuf[i] = (FLAC__int32)(((FLAC__int16)(FLAC__int8)pbtStream[2*i+1] << 8) | (FLAC__int16)pbtStream[2*i]);
+ }
+
+ // feed samples to encoder
+ if (!m_dll.FLAC__stream_encoder_process_interleaved(m_encoder, m_samplesBuf, nSamples / 2))
+ {
+ CLog::Log(LOGERROR, "FLAC__stream_encoder_process_interleaved error");
+ return 0;
+ }
+
+ nLeftSamples -= nSamples;
+ pbtStream += nSamples * 2; // skip processed samples
+ }
+
+ return 1;
+}
+
+bool CEncoderFlac::Close()
+{
+ FLAC__bool ok = 0;
+
+ if (m_encoder)
+ {
+ // finish encoding
+ ok = m_dll.FLAC__stream_encoder_finish(m_encoder);
+ if (!ok)
+ CLog::Log(LOGERROR, "FLAC encoder finish error");
+
+ // now that encoding is finished, the metadata can be freed
+ if (m_metadata[0])
+ m_dll.FLAC__metadata_object_delete(m_metadata[0]);
+
+ // delete encoder
+ m_dll.FLAC__stream_encoder_delete(m_encoder);
+ }
+
+ FileClose();
+
+ return ok ? true : false;
+}
+
+FLAC__StreamEncoderWriteStatus CEncoderFlac::write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data)
+{
+ CEncoderFlac *pThis = (CEncoderFlac *)client_data;
+ if (pThis->FileWrite(buffer, bytes) != bytes)
+ return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
+ return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
+}
+
+FLAC__StreamEncoderSeekStatus CEncoderFlac::seek_callback(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
+{
+ CEncoderFlac *pThis = (CEncoderFlac *)client_data;
+ if (pThis->m_file->Seek(absolute_byte_offset, FILE_BEGIN) < 0)
+ return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR;
+ return FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
+}
+
+FLAC__StreamEncoderTellStatus CEncoderFlac::tell_callback(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
+{
+ CEncoderFlac *pThis = (CEncoderFlac *)client_data;
+ int64_t off = pThis->m_file->GetLength();
+ if (off < 0)
+ return FLAC__STREAM_ENCODER_TELL_STATUS_ERROR;
+ *absolute_byte_offset = off;
+ return FLAC__STREAM_ENCODER_TELL_STATUS_OK;
+}
diff --git a/xbmc/cdrip/EncoderFlac.h b/xbmc/cdrip/EncoderFlac.h new file mode 100644 index 0000000000..f375153018 --- /dev/null +++ b/xbmc/cdrip/EncoderFlac.h @@ -0,0 +1,50 @@ +#ifndef _ENCODERFLAC_H
+#define _ENCODERFLAC_H
+
+/*
+ * Copyright (C) 2005-2008 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "Encoder.h"
+#include "DllFlacEnc.h"
+
+class CEncoderFlac : public CEncoder
+{
+public:
+ CEncoderFlac();
+ virtual ~CEncoderFlac();
+ bool Init(const char* strFile, int iInChannels, int iInRate, int iInBits);
+ int Encode(int nNumBytesRead, uint8_t* pbtStream);
+ bool Close();
+
+private:
+ DllFlacEnc m_dll;
+ FLAC__StreamEncoder *m_encoder;
+ FLAC__StreamMetadata *m_metadata[1];
+
+ static const int SAMPLES_BUF_SIZE = 1024 * 2;
+ FLAC__int32 *m_samplesBuf;
+
+ static FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data);
+ static FLAC__StreamEncoderSeekStatus seek_callback(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
+ static FLAC__StreamEncoderTellStatus tell_callback(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
+};
+
+#endif // _ENCODERFLAC_H
diff --git a/xbmc/cdrip/Makefile.in b/xbmc/cdrip/Makefile.in index 9e887cc011..e33f8842ac 100644 --- a/xbmc/cdrip/Makefile.in +++ b/xbmc/cdrip/Makefile.in @@ -9,6 +9,7 @@ SRCS=CDDARipper.cpp \ EncoderLame.cpp \ EncoderVorbis.cpp \ EncoderWav.cpp \ + EncoderFlac.cpp \ LIB=cdrip.a |