void startAudioCapture() { if (audioDeviceInfo.isNull()) { audioInput = nullptr; return; } audioInput = std::make_unique<QAudioInput>(audioDeviceInfo, audioFormat); QIODevice * audioDevice = audioInput->start(); audioBuffer.clear(); QObject::connect(audioDevice, &QIODevice::readyRead, audioDevice, [=](){ audioBuffer += audioDevice->readAll(); int frameSize = 1024 * audioFormat.channelCount(); while (audioBuffer.size() > frameSize) { QByteArray data = audioBuffer.left(frameSize); audioBuffer.remove(0, frameSize); writeAudioFrame(audioStreamIndex, data); } }); }
void EncoderFfmpegCore::encodeBuffer(const CSAMPLE *samples, const int size) { unsigned char *l_strBuffer = NULL; int l_iBufferLen = 0; //int l_iAudioCpyLen = m_iAudioInputFrameSize * // av_get_bytes_per_sample(m_pEncoderAudioStream->codec->sample_fmt) * // m_pEncoderAudioStream->codec->channels; long l_iLeft = size; long j = 0; unsigned int l_iBufPos = 0; unsigned int l_iPos = 0; // TODO(XXX): Get rid of repeated malloc here! float *l_fNormalizedSamples = (float *)malloc(size * sizeof(float)); // We use normalized floats in the engine [-1.0, 1.0] and FFMPEG expects // samples in the range [-1.0, 1.0] so no conversion is required. for (j = 0; j < size; j++) { l_fNormalizedSamples[j] = samples[j]; } // In MP3 this writes Header same In ogg // They are written once front of the encoded stuff if (m_bStreamInitialized == false) { m_bStreamInitialized = true; // Write a header. avio_open_dyn_buf(&m_pEncodeFormatCtx->pb); if (avformat_write_header(m_pEncodeFormatCtx, NULL) != 0) { qDebug() << "EncoderFfmpegCore::encodeBuffer: failed to write a header."; return; } l_iBufferLen = avio_close_dyn_buf(m_pEncodeFormatCtx->pb, (uint8_t**)(&l_strBuffer)); m_pCallback->write(NULL, l_strBuffer, 0, l_iBufferLen); av_free(l_strBuffer); } while (l_iLeft > (m_iFltAudioCpyLen / 4)) { memset(m_pFltSamples, 0x00, m_iFltAudioCpyLen); for (j = 0; j < m_iFltAudioCpyLen / 4; j++) { if (m_lBufferSize > 0) { m_pFltSamples[j] = m_SBuffer[ l_iBufPos++ ]; m_lBufferSize--; m_lRecordedBytes++; } else { m_pFltSamples[j] = l_fNormalizedSamples[l_iPos++]; l_iLeft--; m_lRecordedBytes++; } if (l_iLeft <= 0) { qDebug() << "ffmpegencodercore: No samples left.. for encoding!"; break; } } m_lBufferSize = 0; // Open dynamic buffer for writing next bytes if (avio_open_dyn_buf(&m_pEncodeFormatCtx->pb) < 0) { qDebug() << "Can't alloc Dyn buffer!"; return; } // Write it to buffer (FILE) and then close buffer for waiting // Next encoded buffe to come or we stop encode if (! writeAudioFrame(m_pEncodeFormatCtx, m_pEncoderAudioStream)) { l_iBufferLen = avio_close_dyn_buf(m_pEncodeFormatCtx->pb, (uint8_t**)(&l_strBuffer)); m_pCallback->write(NULL, l_strBuffer, 0, l_iBufferLen); av_free(l_strBuffer); } } // Keep things clean memset(m_SBuffer, 0x00, 65535); for (j = 0; j < l_iLeft; j++) { m_SBuffer[ j ] = l_fNormalizedSamples[ l_iPos++ ]; } m_lBufferSize = l_iLeft; free(l_fNormalizedSamples); }