Use CC0-1.0 licensed decoder 'minimp3' to replace LGPL licensed decoder 'mpg123'

This commit is contained in:
halx99 2020-08-17 14:56:53 +08:00
parent b090664084
commit bda3a720b4
5 changed files with 132 additions and 35 deletions

View File

@ -25,7 +25,7 @@ set(COCOS_AUDIO_SRC
# stupid, clang always compie .mm as objc/cpp mix obj # stupid, clang always compie .mm as objc/cpp mix obj
if(ANDROID) if(ANDROID)
set(COCOS_AUDIO_SRC ${COCOS_AUDIO_SRC} set(COCOS_AUDIO_SRC ${COCOS_AUDIO_SRC}
audio/src/alink.cpp audio/src/android-link.cpp
) )
else() else()
set(COCOS_AUDIO_SRC ${COCOS_AUDIO_SRC} set(COCOS_AUDIO_SRC ${COCOS_AUDIO_SRC}

View File

@ -28,7 +28,15 @@
#include "audio/include/AudioDecoder.h" #include "audio/include/AudioDecoder.h"
#include "platform/PXFileStream.h" #include "platform/PXFileStream.h"
struct mpg123_handle_struct; #if !defined(CC_USE_MPG123)
#define CC_USE_MPG123 0
#endif
#if !CC_USE_MPG123
typedef struct mp3dec_impl* mp3dec_handle_t;
#else
typedef struct mpg123_handle_struct* mp3dec_handle_t;
#endif
namespace cocos2d { namespace cocos2d {
@ -74,7 +82,7 @@ protected:
static void destroy(); static void destroy();
PXFileStream _fileStream; PXFileStream _fileStream;
struct mpg123_handle_struct* _mpg123handle; mp3dec_handle_t _handle;
friend class AudioDecoderManager; friend class AudioDecoderManager;
}; };

View File

@ -21,7 +21,7 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
****************************************************************************/ ****************************************************************************/
#define LOG_TAG "AudioDecoderManager" #define LOG_TAG "AudioDecoderManager"
@ -67,7 +67,7 @@ AudioDecoder* AudioDecoderManager::createDecoder(const std::string& path)
} }
#if CC_TARGET_PLATFORM != CC_PLATFORM_IOS #if CC_TARGET_PLATFORM != CC_PLATFORM_IOS
else if (cxx20::ic::ends_with(svPath, ".mp3")) else if (cxx20::ic::ends_with(svPath, ".mp3"))
{ {
return new (std::nothrow) AudioDecoderMp3(); return new (std::nothrow) AudioDecoderMp3();
} }
else if (cxx20::ic::ends_with(svPath, ".wav")) { else if (cxx20::ic::ends_with(svPath, ".wav")) {

View File

@ -1,6 +1,7 @@
/**************************************************************************** /****************************************************************************
Copyright (c) 2016 Chukong Technologies Inc. Copyright (c) 2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
Copyright (c) 2020 c4games.com
http://www.cocos2d-x.org http://www.cocos2d-x.org
@ -29,17 +30,40 @@
#include "platform/CCFileUtils.h" #include "platform/CCFileUtils.h"
#include "base/CCConsole.h" #include "base/CCConsole.h"
#if !CC_USE_MPG123
#define MINIMP3_IMPLEMENTATION
#include "minimp3/minimp3_ex.h"
#else
// because the cocos2d-x engine has ssize_t typedef, so disable mpg123 ssize_t // because the cocos2d-x engine has ssize_t typedef, so disable mpg123 ssize_t
#define MPG123_DEF_SSIZE_T #define MPG123_DEF_SSIZE_T
#include "mpg123.h" #include "mpg123.h"
#endif
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
#endif #endif
namespace cocos2d { #if !CC_USE_MPG123
struct mp3dec_impl {
mp3dec_ex_t _dec;
mp3dec_io_t _decIO;
};
#endif
namespace cocos2d {
#if !CC_USE_MPG123
static size_t minimp3_read_r(void* buf, size_t size, void* user_data)
{
return ((PXFileStream*)user_data)->read(buf, size);
}
static int minimp3_seek_r(uint64_t position, void* user_data)
{
return ((PXFileStream*)user_data)->seek(position, SEEK_SET) >= 0 ? 0 : -1;
}
#else
static bool __mp3Inited = false; static bool __mp3Inited = false;
static ssize_t mpg123_read_r(void * handle, void * buffer, size_t count) static ssize_t mpg123_read_r(void * handle, void * buffer, size_t count)
@ -55,10 +79,11 @@ namespace cocos2d {
void mpg123_close_r(void* handle) { void mpg123_close_r(void* handle) {
((PXFileStream*)handle)->close(); ((PXFileStream*)handle)->close();
} }
#endif
bool AudioDecoderMp3::lazyInit() bool AudioDecoderMp3::lazyInit()
{ {
bool ret = true; bool ret = true;
#if CC_USE_MPG123
if (!__mp3Inited) if (!__mp3Inited)
{ {
int error = mpg123_init(); int error = mpg123_init();
@ -72,20 +97,23 @@ namespace cocos2d {
ret = false; ret = false;
} }
} }
#endif
return ret; return ret;
} }
void AudioDecoderMp3::destroy() void AudioDecoderMp3::destroy()
{ {
#if CC_USE_MPG123
if (__mp3Inited) if (__mp3Inited)
{ {
mpg123_exit(); mpg123_exit();
__mp3Inited = false; __mp3Inited = false;
} }
#endif
} }
AudioDecoderMp3::AudioDecoderMp3() AudioDecoderMp3::AudioDecoderMp3()
: _mpg123handle(nullptr) : _handle(nullptr)
{ {
lazyInit(); lazyInit();
} }
@ -97,14 +125,57 @@ namespace cocos2d {
bool AudioDecoderMp3::open(const std::string& fullPath) bool AudioDecoderMp3::open(const std::string& fullPath)
{ {
#if !CC_USE_MPG123
do
{
if (!_fileStream.open(fullPath))
{
ALOGE("Trouble with minimp3(1): %s\n", strerror(errno));
break;
}
auto handle = new mp3dec_impl();
handle->_decIO.read = minimp3_read_r;
handle->_decIO.seek = minimp3_seek_r;
handle->_decIO.read_data = handle->_decIO.seek_data = &_fileStream;
if (mp3dec_ex_open_cb(&handle->_dec, &handle->_decIO, MP3D_SEEK_TO_SAMPLE) != 0)
{
delete handle;
break;
}
auto& info = handle->_dec.info;
_channelCount = info.channels; // the _channelCount is samplesPerFrame
_sampleRate = info.hz;
#ifndef MINIMP3_FLOAT_OUTPUT
_sourceFormat = AUDIO_SOURCE_FORMAT::PCM_16;
_bytesPerBlock = sizeof(uint16_t) * _channelCount;
#else
_sourceFormat = AUDIO_SOURCE_FORMAT::PCM_FLT32;
_bytesPerBlock = sizeof(float) * _channelCount;
#endif
// samples
_totalFrames = handle->_dec.samples / _channelCount;
// store the handle
_handle = handle;
_isOpened = true;
return true;
} while (false);
return false;
#else
long rate = 0; long rate = 0;
int error = MPG123_OK; int error = MPG123_OK;
int mp3Encoding = 0; int mp3Encoding = 0;
int channel = 0; int channel = 0;
do do
{ {
_mpg123handle = mpg123_new(nullptr, &error); _handle = mpg123_new(nullptr, &error);
if (nullptr == _mpg123handle) if (nullptr == _handle)
{ {
ALOGE("Basic setup goes wrong: %s", mpg123_plain_strerror(error)); ALOGE("Basic setup goes wrong: %s", mpg123_plain_strerror(error));
break; break;
@ -116,12 +187,12 @@ namespace cocos2d {
break; break;
} }
mpg123_replace_reader_handle(_mpg123handle, mpg123_read_r, mpg123_lseek_r, mpg123_close_r); mpg123_replace_reader_handle(_handle, mpg123_read_r, mpg123_lseek_r, mpg123_close_r);
if (mpg123_open_handle(_mpg123handle, &_fileStream) != MPG123_OK if (mpg123_open_handle(_handle, &_fileStream) != MPG123_OK
|| mpg123_getformat(_mpg123handle, &rate, &channel, &mp3Encoding) != MPG123_OK) || mpg123_getformat(_handle, &rate, &channel, &mp3Encoding) != MPG123_OK)
{ {
ALOGE("Trouble with mpg123(2): %s\n", mpg123_strerror(_mpg123handle)); ALOGE("Trouble with mpg123(2): %s\n", mpg123_strerror(_handle));
break; break;
} }
@ -145,62 +216,80 @@ namespace cocos2d {
} }
/* Ensure that this output format will not change (it could, when we allow it). */ /* Ensure that this output format will not change (it could, when we allow it). */
mpg123_format_none(_mpg123handle); mpg123_format_none(_handle);
mpg123_format(_mpg123handle, rate, channel, mp3Encoding); mpg123_format(_handle, rate, channel, mp3Encoding);
/* Ensure that we can get accurate length by call mpg123_length */ /* Ensure that we can get accurate length by call mpg123_length */
mpg123_scan(_mpg123handle); mpg123_scan(_handle);
_totalFrames = mpg123_length(_mpg123handle); _totalFrames = mpg123_length(_handle);
_isOpened = true; _isOpened = true;
return true; return true;
} while (false); } while (false);
if (_mpg123handle != nullptr) if (_handle != nullptr)
{ {
mpg123_close(_mpg123handle); mpg123_close(_handle);
mpg123_delete(_mpg123handle); mpg123_delete(_handle);
_mpg123handle = nullptr; _handle = nullptr;
} }
return false; return false;
#endif
} }
void AudioDecoderMp3::close() void AudioDecoderMp3::close()
{ {
if (isOpened()) if (isOpened())
{ {
if (_mpg123handle != nullptr) #if !CC_USE_MPG123
{ if (_handle) {
mpg123_close(_mpg123handle); mp3dec_ex_close(&_handle->_dec);
mpg123_delete(_mpg123handle);
_mpg123handle = nullptr; delete _handle;
_handle = nullptr;
_fileStream.close();
} }
#else
if (_handle != nullptr)
{
mpg123_close(_handle);
mpg123_delete(_handle);
_handle = nullptr;
}
#endif
_isOpened = false; _isOpened = false;
} }
} }
uint32_t AudioDecoderMp3::read(uint32_t framesToRead, char* pcmBuf) uint32_t AudioDecoderMp3::read(uint32_t framesToRead, char* pcmBuf)
{ {
#if !CC_USE_MPG123
auto sampelsToRead = framesToRead * _channelCount;
auto samplesRead = mp3dec_ex_read(&_handle->_dec, (mp3d_sample_t*)pcmBuf, sampelsToRead);
return static_cast<uint32_t>(samplesRead / _channelCount);
#else
int bytesToRead = framesToBytes(framesToRead); int bytesToRead = framesToBytes(framesToRead);
size_t bytesRead = 0; size_t bytesRead = 0;
int err = mpg123_read(_mpg123handle, (unsigned char*)pcmBuf, bytesToRead, &bytesRead); int err = mpg123_read(_handle, (unsigned char*)pcmBuf, bytesToRead, &bytesRead);
if (err == MPG123_ERR) if (err == MPG123_ERR)
{ {
ALOGE("Trouble with mpg123: %s\n", mpg123_strerror(_mpg123handle) ); ALOGE("Trouble with mpg123: %s\n", mpg123_strerror(_handle) );
return 0; return 0;
} }
return bytesToFrames(bytesRead); return bytesToFrames(bytesRead);
#endif
} }
bool AudioDecoderMp3::seek(uint32_t frameOffset) bool AudioDecoderMp3::seek(uint32_t frameOffset)
{ {
off_t offset = mpg123_seek(_mpg123handle, frameOffset, SEEK_SET); #if !CC_USE_MPG123
return 0 == mp3dec_ex_seek(&_handle->_dec, frameOffset);
#else
off_t offset = mpg123_seek(_handle, frameOffset, SEEK_SET);
//ALOGD("mpg123_seek return: %d", (int)offset); //ALOGD("mpg123_seek return: %d", (int)offset);
if (offset >= 0 && offset == frameOffset) return (offset >= 0 && offset == frameOffset);
{ #endif
return true;
}
return false;
} }
} // namespace cocos2d { } // namespace cocos2d {