mirror of https://github.com/procxx/kepka.git
ffmpeg audio play / capture done in os x
This commit is contained in:
parent
1b11a7feae
commit
1b06fe1220
|
@ -30,6 +30,30 @@ extern "C" {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
#include <iconv.h>
|
||||||
|
|
||||||
|
#undef iconv_open
|
||||||
|
#undef iconv
|
||||||
|
#undef iconv_close
|
||||||
|
|
||||||
|
iconv_t iconv_open (const char* tocode, const char* fromcode) {
|
||||||
|
return libiconv_open(tocode, fromcode);
|
||||||
|
}
|
||||||
|
size_t iconv (iconv_t cd, char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft) {
|
||||||
|
return libiconv(cd, inbuf, inbytesleft, outbuf, outbytesleft);
|
||||||
|
}
|
||||||
|
int iconv_close (iconv_t cd) {
|
||||||
|
return libiconv_close(cd);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
ALCdevice *audioDevice = 0;
|
ALCdevice *audioDevice = 0;
|
||||||
ALCcontext *audioContext = 0;
|
ALCcontext *audioContext = 0;
|
||||||
|
@ -285,48 +309,53 @@ bool AudioPlayer::updateCurrentStarted(int32 pos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayer::play(AudioData *audio) {
|
void AudioPlayer::play(AudioData *audio) {
|
||||||
QMutexLocker lock(&playerMutex);
|
AudioData *stopped = 0;
|
||||||
|
|
||||||
bool startNow = true;
|
{
|
||||||
if (_data[_current].audio != audio) {
|
QMutexLocker lock(&playerMutex);
|
||||||
switch (_data[_current].state) {
|
|
||||||
case AudioPlayerStarting:
|
|
||||||
case AudioPlayerResuming:
|
|
||||||
case AudioPlayerPlaying:
|
|
||||||
_data[_current].state = AudioPlayerFinishing;
|
|
||||||
updateCurrentStarted();
|
|
||||||
startNow = false;
|
|
||||||
break;
|
|
||||||
case AudioPlayerPausing: _data[_current].state = AudioPlayerFinishing; startNow = false; break;
|
|
||||||
case AudioPlayerPaused: _data[_current].state = AudioPlayerStopped; break;
|
|
||||||
}
|
|
||||||
if (_data[_current].audio) {
|
|
||||||
emit loaderOnCancel(_data[_current].audio);
|
|
||||||
emit faderOnTimer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 index = 0;
|
bool startNow = true;
|
||||||
for (; index < AudioVoiceMsgSimultaneously; ++index) {
|
if (_data[_current].audio != audio) {
|
||||||
if (_data[index].audio == audio) {
|
switch (_data[_current].state) {
|
||||||
_current = index;
|
case AudioPlayerStarting:
|
||||||
break;
|
case AudioPlayerResuming:
|
||||||
|
case AudioPlayerPlaying:
|
||||||
|
_data[_current].state = AudioPlayerFinishing;
|
||||||
|
updateCurrentStarted();
|
||||||
|
startNow = false;
|
||||||
|
break;
|
||||||
|
case AudioPlayerPausing: _data[_current].state = AudioPlayerFinishing; startNow = false; break;
|
||||||
|
case AudioPlayerPaused: _data[_current].state = AudioPlayerStopped; stopped = _data[_current].audio; break;
|
||||||
|
}
|
||||||
|
if (_data[_current].audio) {
|
||||||
|
emit loaderOnCancel(_data[_current].audio);
|
||||||
|
emit faderOnTimer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 index = 0;
|
||||||
|
for (; index < AudioVoiceMsgSimultaneously; ++index) {
|
||||||
|
if (_data[index].audio == audio) {
|
||||||
|
_current = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index == AudioVoiceMsgSimultaneously && ++_current >= AudioVoiceMsgSimultaneously) {
|
||||||
|
_current -= AudioVoiceMsgSimultaneously;
|
||||||
|
}
|
||||||
|
_data[_current].audio = audio;
|
||||||
|
_data[_current].fname = audio->already(true);
|
||||||
|
_data[_current].data = audio->data;
|
||||||
|
if (_data[_current].fname.isEmpty() && _data[_current].data.isEmpty()) {
|
||||||
|
_data[_current].state = AudioPlayerStopped;
|
||||||
|
onError(audio);
|
||||||
|
} else if (updateCurrentStarted(0)) {
|
||||||
|
_data[_current].state = startNow ? AudioPlayerPlaying : AudioPlayerStarting;
|
||||||
|
_data[_current].loading = true;
|
||||||
|
emit loaderOnStart(audio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (index == AudioVoiceMsgSimultaneously && ++_current >= AudioVoiceMsgSimultaneously) {
|
if (stopped) emit updated(stopped);
|
||||||
_current -= AudioVoiceMsgSimultaneously;
|
|
||||||
}
|
|
||||||
_data[_current].audio = audio;
|
|
||||||
_data[_current].fname = audio->already(true);
|
|
||||||
_data[_current].data = audio->data;
|
|
||||||
if (_data[_current].fname.isEmpty() && _data[_current].data.isEmpty()) {
|
|
||||||
_data[_current].state = AudioPlayerStopped;
|
|
||||||
onError(audio);
|
|
||||||
} else if (updateCurrentStarted(0)) {
|
|
||||||
_data[_current].state = startNow ? AudioPlayerPlaying : AudioPlayerStarting;
|
|
||||||
_data[_current].loading = true;
|
|
||||||
emit loaderOnStart(audio);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayer::pauseresume() {
|
void AudioPlayer::pauseresume() {
|
||||||
|
@ -491,7 +520,7 @@ void AudioPlayerFader::onTimer() {
|
||||||
emit audioStopped(m.audio);
|
emit audioStopped(m.audio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pos + m.skipStart - m.position >= AudioCheckPositionDelta) {
|
if (state == AL_PLAYING && pos + m.skipStart - m.position >= AudioCheckPositionDelta) {
|
||||||
m.position = pos + m.skipStart;
|
m.position = pos + m.skipStart;
|
||||||
emit playPositionUpdated(m.audio);
|
emit playPositionUpdated(m.audio);
|
||||||
}
|
}
|
||||||
|
@ -739,7 +768,7 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (avpkt.stream_index == streamId) {
|
if (avpkt.stream_index == streamId) {
|
||||||
avcodec_get_frame_defaults(frame);
|
av_frame_unref(frame);
|
||||||
int got_frame = 0;
|
int got_frame = 0;
|
||||||
if ((res = avcodec_decode_audio4(codecContext, frame, &got_frame, &avpkt)) < 0) {
|
if ((res = avcodec_decode_audio4(codecContext, frame, &got_frame, &avpkt)) < 0) {
|
||||||
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
|
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
|
||||||
|
@ -800,7 +829,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int32 freq, fmt, channels;
|
int32 freq, fmt;
|
||||||
int32 sampleSize, srcRate, dstRate, maxResampleSamples;
|
int32 sampleSize, srcRate, dstRate, maxResampleSamples;
|
||||||
uint8_t **dstSamplesData;
|
uint8_t **dstSamplesData;
|
||||||
int64 len;
|
int64 len;
|
||||||
|
@ -1054,6 +1083,8 @@ void AudioPlayerLoaders::onLoad(AudioData *audio) {
|
||||||
if (finished) {
|
if (finished) {
|
||||||
m.skipEnd = 0;
|
m.skipEnd = 0;
|
||||||
m.duration = m.skipStart + m.samplesCount[0] + m.samplesCount[1] + m.samplesCount[2];
|
m.duration = m.skipStart + m.samplesCount[0] + m.samplesCount[1] + m.samplesCount[2];
|
||||||
|
delete j.value();
|
||||||
|
_loaders.erase(j);
|
||||||
}
|
}
|
||||||
m.loading = false;
|
m.loading = false;
|
||||||
if (m.state == AudioPlayerResuming || m.state == AudioPlayerPlaying || m.state == AudioPlayerStarting) {
|
if (m.state == AudioPlayerResuming || m.state == AudioPlayerPlaying || m.state == AudioPlayerStarting) {
|
||||||
|
@ -1172,7 +1203,7 @@ void AudioCaptureInner::onStart() {
|
||||||
|
|
||||||
// Start OpenAL Capture
|
// Start OpenAL Capture
|
||||||
|
|
||||||
d->device = alcCaptureOpenDevice(0, AudioVoiceMsgFrequency, AL_FORMAT_MONO16, AudioVoiceMsgBufferSize);
|
d->device = alcCaptureOpenDevice(0, AudioVoiceMsgFrequency, AL_FORMAT_MONO16, AudioVoiceMsgFrequency / 5);
|
||||||
if (!d->device) {
|
if (!d->device) {
|
||||||
LOG(("Audio Error: capture device not present!"));
|
LOG(("Audio Error: capture device not present!"));
|
||||||
emit error();
|
emit error();
|
||||||
|
@ -1457,7 +1488,7 @@ void AudioCaptureInner::onTimeout() {
|
||||||
}
|
}
|
||||||
// Write frames
|
// Write frames
|
||||||
int32 framesize = d->srcSamples * d->codecContext->channels * sizeof(short), encoded = 0;
|
int32 framesize = d->srcSamples * d->codecContext->channels * sizeof(short), encoded = 0;
|
||||||
while (_captured.size() >= encoded + framesize + fadeSamples * sizeof(short)) {
|
while (uint32(_captured.size()) >= encoded + framesize + fadeSamples * sizeof(short)) {
|
||||||
writeFrame(encoded, framesize);
|
writeFrame(encoded, framesize);
|
||||||
encoded += framesize;
|
encoded += framesize;
|
||||||
}
|
}
|
||||||
|
@ -1527,8 +1558,9 @@ void AudioCaptureInner::writeFrame(int32 offset, int32 framesize) {
|
||||||
|
|
||||||
// Write audio frame
|
// Write audio frame
|
||||||
|
|
||||||
AVPacket pkt = { 0 }; // data and size must be 0;
|
AVPacket pkt;
|
||||||
AVFrame *frame = avcodec_alloc_frame();
|
memset(&pkt, 0, sizeof(pkt)); // data and size must be 0;
|
||||||
|
AVFrame *frame = av_frame_alloc();
|
||||||
int gotPacket;
|
int gotPacket;
|
||||||
av_init_packet(&pkt);
|
av_init_packet(&pkt);
|
||||||
|
|
||||||
|
@ -1552,5 +1584,5 @@ void AudioCaptureInner::writeFrame(int32 offset, int32 framesize) {
|
||||||
}
|
}
|
||||||
d->fullSamples += samplesCnt;
|
d->fullSamples += samplesCnt;
|
||||||
|
|
||||||
avcodec_free_frame(&frame);
|
av_frame_free(&frame);
|
||||||
}
|
}
|
|
@ -35,6 +35,9 @@ enum AudioPlayerState {
|
||||||
AudioPlayerResuming,
|
AudioPlayerResuming,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AudioPlayerFader;
|
||||||
|
class AudioPlayerLoaders;
|
||||||
|
|
||||||
class AudioPlayer : public QObject {
|
class AudioPlayer : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -104,6 +107,8 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AudioCaptureInner;
|
||||||
|
|
||||||
class AudioCapture : public QObject {
|
class AudioCapture : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -199,6 +204,8 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AudioCapturePrivate;
|
||||||
|
|
||||||
class AudioCaptureInner : public QObject {
|
class AudioCaptureInner : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -225,7 +232,6 @@ private:
|
||||||
|
|
||||||
void writeFrame(int32 offset, int32 framesize);
|
void writeFrame(int32 offset, int32 framesize);
|
||||||
|
|
||||||
friend struct AudioCapturePrivate;
|
|
||||||
AudioCapturePrivate *d;
|
AudioCapturePrivate *d;
|
||||||
QTimer _timer;
|
QTimer _timer;
|
||||||
QByteArray _captured;
|
QByteArray _captured;
|
||||||
|
|
|
@ -3031,6 +3031,7 @@ void HistoryWidget::stopRecording(bool send) {
|
||||||
_recordingAnim.stop();
|
_recordingAnim.stop();
|
||||||
|
|
||||||
_recording = false;
|
_recording = false;
|
||||||
|
_recordingSamples = 0;
|
||||||
updateControlsVisibility();
|
updateControlsVisibility();
|
||||||
activate();
|
activate();
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ typedef QList<ToPrepareMedia> ToPrepareMedias;
|
||||||
typedef QMap<int32, QByteArray> LocalFileParts;
|
typedef QMap<int32, QByteArray> LocalFileParts;
|
||||||
struct ReadyLocalMedia {
|
struct ReadyLocalMedia {
|
||||||
ReadyLocalMedia(ToPrepareMediaType type, const QString &file, const QString &filename, int32 filesize, const QByteArray &data, const uint64 &id, const uint64 &thumbId, const QString &thumbExt, const PeerId &peer, const MTPPhoto &photo, const MTPAudio &audio, const PreparedPhotoThumbs &photoThumbs, const MTPDocument &document, const QByteArray &jpeg, bool ctrlShiftEnter, MsgId replyTo) :
|
ReadyLocalMedia(ToPrepareMediaType type, const QString &file, const QString &filename, int32 filesize, const QByteArray &data, const uint64 &id, const uint64 &thumbId, const QString &thumbExt, const PeerId &peer, const MTPPhoto &photo, const MTPAudio &audio, const PreparedPhotoThumbs &photoThumbs, const MTPDocument &document, const QByteArray &jpeg, bool ctrlShiftEnter, MsgId replyTo) :
|
||||||
replyTo(replyTo), type(type), file(file), filename(filename), filesize(filesize), data(data), thumbExt(thumbExt), id(id), thumbId(thumbId), peer(peer), photo(photo), document(document), photoThumbs(photoThumbs), audio(audio), ctrlShiftEnter(ctrlShiftEnter) {
|
replyTo(replyTo), type(type), file(file), filename(filename), filesize(filesize), data(data), thumbExt(thumbExt), id(id), thumbId(thumbId), peer(peer), photo(photo), document(document), audio(audio), photoThumbs(photoThumbs), ctrlShiftEnter(ctrlShiftEnter) {
|
||||||
if (!jpeg.isEmpty()) {
|
if (!jpeg.isEmpty()) {
|
||||||
int32 size = jpeg.size();
|
int32 size = jpeg.size();
|
||||||
for (int32 i = 0, part = 0; i < size; i += UploadPartSize, ++part) {
|
for (int32 i = 0, part = 0; i < size; i += UploadPartSize, ++part) {
|
||||||
|
|
|
@ -1863,6 +1863,11 @@
|
||||||
/usr/local/lib/libmpg123.a,
|
/usr/local/lib/libmpg123.a,
|
||||||
/usr/local/lib/libfaad.a,
|
/usr/local/lib/libfaad.a,
|
||||||
/usr/local/lib/libmp4ff.a,
|
/usr/local/lib/libmp4ff.a,
|
||||||
|
/usr/local/lib/libavcodec.a,
|
||||||
|
/usr/local/lib/libavformat.a,
|
||||||
|
/usr/local/lib/libswresample.a,
|
||||||
|
/usr/local/lib/libavutil.a,
|
||||||
|
/usr/local/lib/libiconv.a,
|
||||||
"../../Libraries/openssl-xcode/libcrypto.a",
|
"../../Libraries/openssl-xcode/libcrypto.a",
|
||||||
);
|
);
|
||||||
PRODUCT_NAME = Telegram;
|
PRODUCT_NAME = Telegram;
|
||||||
|
@ -2010,6 +2015,11 @@
|
||||||
/usr/local/lib/libmpg123.a,
|
/usr/local/lib/libmpg123.a,
|
||||||
/usr/local/lib/libfaad.a,
|
/usr/local/lib/libfaad.a,
|
||||||
/usr/local/lib/libmp4ff.a,
|
/usr/local/lib/libmp4ff.a,
|
||||||
|
/usr/local/lib/libavcodec.a,
|
||||||
|
/usr/local/lib/libavformat.a,
|
||||||
|
/usr/local/lib/libswresample.a,
|
||||||
|
/usr/local/lib/libavutil.a,
|
||||||
|
/usr/local/lib/libiconv.a,
|
||||||
"../../Libraries/openssl-xcode/libcrypto.a",
|
"../../Libraries/openssl-xcode/libcrypto.a",
|
||||||
);
|
);
|
||||||
PRODUCT_NAME = Telegram;
|
PRODUCT_NAME = Telegram;
|
||||||
|
|
|
@ -131,6 +131,7 @@ GeneratedFiles/Debug/moc_application.cpp: ../../Libraries/QtStatic/qtbase/includ
|
||||||
/usr/local/Qt-5.4.0/bin/moc $(DEFINES) -D__APPLE__ -D__GNUC__=4 -I/usr/local/Qt-5.4.0/mkspecs/macx-clang -I. -I/usr/local/Qt-5.4.0/include/QtGui/5.4.0/QtGui -I/usr/local/Qt-5.4.0/include/QtCore/5.4.0/QtCore -I/usr/local/Qt-5.4.0/include -I./SourceFiles -I./GeneratedFiles -I../../Libraries/lzma/C -I../../Libraries/libexif-0.6.20 -I/usr/local/Qt-5.4.0/include -I/usr/local/Qt-5.4.0/include/QtMultimedia -I/usr/local/Qt-5.4.0/include/QtWidgets -I/usr/local/Qt-5.4.0/include/QtNetwork -I/usr/local/Qt-5.4.0/include/QtGui -I/usr/local/Qt-5.4.0/include/QtCore -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/c++/4.2.1 -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/c++/4.2.1/backward -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/5.1/include -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include SourceFiles/application.h -o GeneratedFiles/Debug/moc_application.cpp
|
/usr/local/Qt-5.4.0/bin/moc $(DEFINES) -D__APPLE__ -D__GNUC__=4 -I/usr/local/Qt-5.4.0/mkspecs/macx-clang -I. -I/usr/local/Qt-5.4.0/include/QtGui/5.4.0/QtGui -I/usr/local/Qt-5.4.0/include/QtCore/5.4.0/QtCore -I/usr/local/Qt-5.4.0/include -I./SourceFiles -I./GeneratedFiles -I../../Libraries/lzma/C -I../../Libraries/libexif-0.6.20 -I/usr/local/Qt-5.4.0/include -I/usr/local/Qt-5.4.0/include/QtMultimedia -I/usr/local/Qt-5.4.0/include/QtWidgets -I/usr/local/Qt-5.4.0/include/QtNetwork -I/usr/local/Qt-5.4.0/include/QtGui -I/usr/local/Qt-5.4.0/include/QtCore -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/c++/4.2.1 -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/c++/4.2.1/backward -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/5.1/include -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include SourceFiles/application.h -o GeneratedFiles/Debug/moc_application.cpp
|
||||||
|
|
||||||
GeneratedFiles/Debug/moc_audio.cpp: SourceFiles/types.h \
|
GeneratedFiles/Debug/moc_audio.cpp: SourceFiles/types.h \
|
||||||
|
SourceFiles/audio.h \
|
||||||
../../Libraries/QtStatic/qtbase/include/QtCore/QReadWriteLock \
|
../../Libraries/QtStatic/qtbase/include/QtCore/QReadWriteLock \
|
||||||
SourceFiles/logs.h \
|
SourceFiles/logs.h \
|
||||||
../../Libraries/QtStatic/qtbase/include/QtCore/QTimer \
|
../../Libraries/QtStatic/qtbase/include/QtCore/QTimer \
|
||||||
|
|
Loading…
Reference in New Issue