diff --git a/OpenBoard.pro b/OpenBoard.pro index 67d38467..491400dd 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -44,6 +44,8 @@ QT += printsupport QT += core INCLUDEPATH += src +INCLUDEPATH += /usr/local/opt/openssl/include +INCLUDEPATH += /usr/local/opt/ffmpeg/include include($$THIRD_PARTY_PATH/libs.pri) include(src/adaptors/adaptors.pri) @@ -162,6 +164,8 @@ macx { LIBS += -framework AVFoundation LIBS += -framework CoreMedia LIBS += -lcrypto + LIBS += -L/usr/local/opt/openssl/lib + LIBS += -L/usr/local/opt/ffmpeg/lib CONFIG(release, debug|release):CONFIG += x86_64 CONFIG(debug, debug|release):CONFIG += x86_64 diff --git a/src/podcast/UBPodcastController.cpp b/src/podcast/UBPodcastController.cpp index efe22027..0fda2825 100644 --- a/src/podcast/UBPodcastController.cpp +++ b/src/podcast/UBPodcastController.cpp @@ -62,8 +62,8 @@ #include "windowsmedia/UBWindowsMediaVideoEncoder.h" #include "windowsmedia/UBWaveRecorder.h" #elif defined(Q_OS_OSX) - #include "quicktime/UBQuickTimeVideoEncoder.h" - #include "quicktime/UBAudioQueueRecorder.h" + #include "ffmpeg/UBFFmpegVideoEncoder.h" + #include "ffmpeg/UBMicrophoneInput.h" #elif defined(Q_OS_LINUX) #include "ffmpeg/UBFFmpegVideoEncoder.h" #include "ffmpeg/UBMicrophoneInput.h" @@ -311,7 +311,7 @@ void UBPodcastController::start() #ifdef Q_OS_WIN mVideoEncoder = new UBWindowsMediaVideoEncoder(this); //deleted on stop #elif defined(Q_OS_OSX) - mVideoEncoder = new UBQuickTimeVideoEncoder(this); //deleted on stop + mVideoEncoder = new UBFFmpegVideoEncoder(this); #elif defined(Q_OS_LINUX) mVideoEncoder = new UBFFmpegVideoEncoder(this); #endif @@ -808,7 +808,7 @@ QStringList UBPodcastController::audioRecordingDevices() #ifdef Q_OS_WIN devices = UBWaveRecorder::waveInDevices(); #elif defined(Q_OS_OSX) - devices = UBAudioQueueRecorder::waveInDevices(); + devices = UBMicrophoneInput::availableDevicesNames(); #elif defined(Q_OS_LINUX) devices = UBMicrophoneInput::availableDevicesNames(); #endif diff --git a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp index 320464dd..0a0eea60 100644 --- a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp +++ b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp @@ -369,6 +369,8 @@ bool UBFFmpegVideoEncoder::init() connect(mAudioInput, SIGNAL(dataAvailable(QByteArray)), this, SLOT(onAudioAvailable(QByteArray))); + mAudioInput->setInputDevice(audioRecordingDevice()); + if (!mAudioInput->init()) { setLastErrorMessage("Couldn't initialize audio input"); return false; @@ -392,13 +394,20 @@ bool UBFFmpegVideoEncoder::init() c = mAudioStream->codec; c->bit_rate = 96000; - c->sample_fmt = audioCodec->sample_fmts[0]; // FLTP by default for AAC + c->sample_fmt = audioCodec->sample_fmts ? audioCodec->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;// FLTP by default for AAC c->sample_rate = mAudioSampleRate; - c->channels = 2; - c->channel_layout = av_get_default_channel_layout(c->channels); - c->profile = FF_PROFILE_AAC_MAIN; - c->time_base = {1, mAudioSampleRate}; - c->strict_std_compliance = -2; // Enable use of experimental codec + c->channel_layout = AV_CH_LAYOUT_STEREO; + c->channels = av_get_channel_layout_nb_channels(c->channel_layout); + + //deprecated on ffmpeg 4 + c->strict_std_compliance = -2;// Enable use of experimental codec + + //https://trac.ffmpeg.org/wiki/Encode/H.264#Profile + //Omit this unless your target device only supports a certain profile + //(see https://trac.ffmpeg.org/wiki/Encode/H.264#Compatibility). + //c->profile = FF_PROFILE_AAC_MAIN; + + c->time_base = { 1, c->sample_rate }; if (mOutputFormatContext->oformat->flags & AVFMT_GLOBALHEADER) c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; @@ -562,9 +571,11 @@ void UBFFmpegVideoEncoder::processAudio(QByteArray &data) } // Convert to destination format + ret = swr_convert(mSwrContext, outSamples, outSamplesCount, (const uint8_t **)&inSamples, inSamplesCount); + if (ret < 0) { qWarning() << "Error converting audio samples: " << avErrorToQString(ret); return; diff --git a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h index 6068a369..c313cfda 100644 --- a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h +++ b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h @@ -36,7 +36,10 @@ extern "C" { #include // Due to the whole ffmpeg / libAV silliness, we have to support libavresample on some platforms -#if LIBAVFORMAT_VERSION_MICRO > 100 +// Should libswresample be used with libavformat.*.*.100 ? compiles fine but crashes in swr_convert (internal call of soxr_create causes a SIGSEV (EXC_BAD_ACCESS)) +// Bad config ? +// With libavresample, no crash, but the sound is inaudible (lot of noise) +#if LIBAVFORMAT_VERSION_MICRO >= 100 #include #else #include diff --git a/src/podcast/ffmpeg/UBMicrophoneInput.cpp b/src/podcast/ffmpeg/UBMicrophoneInput.cpp index ad17dd49..b86cdfd8 100644 --- a/src/podcast/ffmpeg/UBMicrophoneInput.cpp +++ b/src/podcast/ffmpeg/UBMicrophoneInput.cpp @@ -42,6 +42,18 @@ bool UBMicrophoneInput::init() } mAudioFormat = mAudioDeviceInfo.preferredFormat(); + + /* + * https://ffmpeg.org/doxygen/3.1/group__lavu__sampfmts.html#gaf9a51ca15301871723577c730b5865c5 + The data described by the sample format is always in native-endian order. + Sample values can be expressed by native C types, hence the lack of a signed 24-bit sample format + even though it is a common raw audio data format. + + If a signed 24-bit sample format is natively preferred, we a set signed 16-bit sample format instead. + */ + if (mAudioFormat.sampleSize() == 24) + mAudioFormat.setSampleSize(16); + mAudioInput = new QAudioInput(mAudioDeviceInfo, mAudioFormat, NULL); connect(mAudioInput, SIGNAL(stateChanged(QAudio::State)), @@ -294,6 +306,8 @@ QString UBMicrophoneInput::getErrorString(QAudio::Error errorCode) case QAudio::FatalError : return "Fatal error; audio device unusable"; + default: + return "unhandled error..."; } return ""; } diff --git a/src/podcast/podcast.pri b/src/podcast/podcast.pri index 91dd3f5d..7e6ea9ee 100644 --- a/src/podcast/podcast.pri +++ b/src/podcast/podcast.pri @@ -23,15 +23,33 @@ win32 { } macx { + CONFIG += c++11 - SOURCES += src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp \ - src/podcast/quicktime/UBAudioQueueRecorder.cpp + SOURCES += src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp \ + src/podcast/ffmpeg/UBMicrophoneInput.cpp - HEADERS += src/podcast/quicktime/UBQuickTimeVideoEncoder.h \ - src/podcast/quicktime/UBQuickTimeFile.h \ - src/podcast/quicktime/UBAudioQueueRecorder.h - - OBJECTIVE_SOURCES += src/podcast/quicktime/UBQuickTimeFile.mm + HEADERS += src/podcast/ffmpeg/UBFFmpegVideoEncoder.h \ + src/podcast/ffmpeg/UBMicrophoneInput.h + + LIBS += -lavformat -lavcodec -lswscale -lswresample -lavutil \ + -lpthread -lvpx -lvorbisenc -lfreetype -llzma -lbz2 -lz -ldl -lavutil -lm + + # (ffmpeg-4.0 with all options (to clean)) + # brew install ffmpeg --with-chromaprint --with-fdk-aac --with-libass --with-librsvg --with-libsoxr --with-libssh --with-tesseract + #--with-libvidstab --with-opencore-amr --with-openh264 --with-openjpeg --with-openssl --with-rtmpdump --with-rubberband --with-sdl2 + #--with-snappy --with-tools --with-webp --with-x265 --with-xz --with-zeromq --with-zimg + # brew install opus + + LIBS += -L/usr/local/opt/x264/lib + LIBS += -L/usr/local/opt/sdl/lib + LIBS += -L/usr/local/opt/libvorbis/lib + LIBS += -L/usr/local/opt/libvpx/lib + LIBS += -L/usr/local/opt/theora/lib + LIBS += -L/usr/local/opt/libogg/lib + LIBS += -L/usr/local/opt/opus/lib + LIBS += -L/usr/local/opt/lame/lib + LIBS += -L/usr/local/opt/fdk-aac/lib + LIBS += -L/usr/local/opt/libass/lib } linux-g++* {