void UBWindowsMediaVideoEncoder::processAudioBuffer(WAVEHDR* waveBuffer, long timestamp) { Q_UNUSED(timestamp); if(mWaveRecorder && mRecordAudio) { long samplesCount = waveBuffer->dwBytesRecorded / 2; qint16* samples = (qint16*)waveBuffer->lpData; quint16 maxRMS = 0; for(long i = 0; i < samplesCount; i++) { quint8 current = qAbs(samples[i] / 128); quint16 currentRMS = current * current; maxRMS = qMax(maxRMS, currentRMS); } quint8 max = sqrt((qreal)maxRMS); if (max != mLastAudioLevel) { mLastAudioLevel = max; emit audioLevelChanged(mLastAudioLevel); } } }
bool UBWindowsMediaVideoEncoder::pause() { bool result = true; if(!mIsPaused && mIsRecording) { if(mWaveRecorder) { result = mWaveRecorder->stop(); emit audioLevelChanged(0); } mIsPaused = true; } return result; }
void UBWindowsMediaVideoEncoder::setRecordAudio(bool pRecordAudio) { if (mRecordAudio != pRecordAudio) { mRecordAudio = pRecordAudio; if (mRecordAudio) { connect(mWaveRecorder, SIGNAL(newWaveBuffer(WAVEHDR*, long)), mWMVideo, SLOT(appendAudioBuffer(WAVEHDR*, long)), Qt::DirectConnection); } else { disconnect(mWaveRecorder, SIGNAL(newWaveBuffer(WAVEHDR*, long)), mWMVideo, SLOT(appendAudioBuffer(WAVEHDR*, long))); emit audioLevelChanged(0); } } }
bool UBWindowsMediaVideoEncoder::stop() { bool audioOk = true; if (mWaveRecorder) { disconnect(mWaveRecorder, SIGNAL(newWaveBuffer(WAVEHDR*, long)), mWMVideo , SLOT(appendAudioBuffer(WAVEHDR*, long))); disconnect(mWaveRecorder, SIGNAL(newWaveBuffer(WAVEHDR*, long)), this , SLOT(processAudioBuffer(WAVEHDR*, long))); mWaveRecorder->stop(); audioOk = mWaveRecorder->close(); mLastErrorMessage = mWaveRecorder->lastErrorMessage(); mWaveRecorder->deleteLater(); mWaveRecorder = 0; emit audioLevelChanged(0); } bool videoOk = true; if (mWMVideo) { videoOk = mWMVideo->close(); mLastErrorMessage = mWMVideo->lastErrorMessage(); mWMVideo->deleteLater(); mWMVideo = 0; } bool ok = audioOk && videoOk; emit encodingFinished(ok); mIsRecording = false; return ok; }
bool UBQuickTimeFile::createCompressionSession() { CodecType codecType = kH264CodecType; CFStringRef keys[] = {kCVPixelBufferPixelFormatTypeKey, kCVPixelBufferWidthKey, kCVPixelBufferHeightKey}; int width = mFrameSize.width(); int height = mFrameSize.height(); int pixelFormat = k32BGRAPixelFormat; CFTypeRef values[] = { (CFTypeRef)CFNumberCreate(0, kCFNumberIntType, (void*)&pixelFormat), (CFTypeRef)CFNumberCreate(0, kCFNumberIntType, (void*)&width), (CFTypeRef)CFNumberCreate(0, kCFNumberIntType, (void*)&height) }; CFDictionaryRef pixelBufferAttributes = CFDictionaryCreate(kCFAllocatorDefault , (const void **)keys, (const void **)values, 3, 0, 0); if(!pixelBufferAttributes) { setLastErrorMessage("Could not create CV buffer pool pixel buffer attributes"); return false; } OSStatus err = noErr; ICMEncodedFrameOutputRecord encodedFrameOutputRecord = {0}; ICMCompressionSessionOptionsRef sessionOptions = 0; err = ICMCompressionSessionOptionsCreate(0, &sessionOptions); if(err) { setLastErrorMessage(QString("ICMCompressionSessionOptionsCreate() failed %1").arg(err)); goto bail; } // We must set this flag to enable P or B frames. err = ICMCompressionSessionOptionsSetAllowTemporalCompression(sessionOptions, true); if(err) { setLastErrorMessage(QString("ICMCompressionSessionOptionsSetAllowTemporalCompression() failed %1").arg(err)); goto bail; } // We must set this flag to enable B frames. err = ICMCompressionSessionOptionsSetAllowFrameReordering(sessionOptions, true); if(err) { setLastErrorMessage(QString("ICMCompressionSessionOptionsSetAllowFrameReordering() failed %1").arg(err)); goto bail; } // Set the maximum key frame interval, also known as the key frame rate. err = ICMCompressionSessionOptionsSetMaxKeyFrameInterval(sessionOptions, mFramesPerSecond); if(err) { setLastErrorMessage(QString("ICMCompressionSessionOptionsSetMaxKeyFrameInterval() failed %1").arg(err)); goto bail; } // This allows the compressor more flexibility (ie, dropping and coalescing frames). err = ICMCompressionSessionOptionsSetAllowFrameTimeChanges(sessionOptions, true); if(err) { setLastErrorMessage(QString("ICMCompressionSessionOptionsSetAllowFrameTimeChanges() failed %1").arg(err)); goto bail; } // Set the average quality. err = ICMCompressionSessionOptionsSetProperty(sessionOptions, kQTPropertyClass_ICMCompressionSessionOptions, kICMCompressionSessionOptionsPropertyID_Quality, sizeof(mSpatialQuality), &mSpatialQuality); if(err) { setLastErrorMessage(QString("ICMCompressionSessionOptionsSetProperty(Quality) failed %1").arg(err)); goto bail; } //qDebug() << "available quality" << mSpatialQuality; encodedFrameOutputRecord.encodedFrameOutputCallback = addEncodedFrameToMovie; encodedFrameOutputRecord.encodedFrameOutputRefCon = this; encodedFrameOutputRecord.frameDataAllocator = 0; err = ICMCompressionSessionCreate(0, mFrameSize.width(), mFrameSize.height(), codecType, mTimeScale, sessionOptions, pixelBufferAttributes, &encodedFrameOutputRecord, &mVideoCompressionSession); if(err) { setLastErrorMessage(QString("ICMCompressionSessionCreate() failed %1").arg(err)); goto bail; } mCVPixelBufferPool = ICMCompressionSessionGetPixelBufferPool(mVideoCompressionSession); if(!mCVPixelBufferPool) { setLastErrorMessage("ICMCompressionSessionGetPixelBufferPool() failed."); err = !noErr; goto bail; } if(mRecordAudio) { mWaveRecorder = new UBAudioQueueRecorder(); if(mWaveRecorder->init(mAudioRecordingDeviceName)) { connect(mWaveRecorder, SIGNAL(newWaveBuffer(void*, long, int , const AudioStreamPacketDescription*)) , this, SLOT(appendAudioBuffer(void*, long, int, const AudioStreamPacketDescription*))); connect(mWaveRecorder, SIGNAL(audioLevelChanged(quint8)), this, SIGNAL(audioLevelChanged(quint8))); } else {