|
|
|
@ -41,18 +41,15 @@ QQueue<UBQuickTimeFile::VideoFrame> UBQuickTimeFile::frameQueue; |
|
|
|
|
QMutex UBQuickTimeFile::frameQueueMutex; |
|
|
|
|
QWaitCondition UBQuickTimeFile::frameBufferNotEmpty; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UBQuickTimeFile::UBQuickTimeFile(QObject * pParent) |
|
|
|
|
: QThread(pParent) |
|
|
|
|
, mVideoWriter(0) |
|
|
|
|
, mVideoWriterInput(0) |
|
|
|
|
, mAdaptor(0) |
|
|
|
|
, mFramesPerSecond(-1) |
|
|
|
|
, mTimeScale(1000) |
|
|
|
|
, mRecordAudio(true) |
|
|
|
|
, mShouldStopCompression(false) |
|
|
|
|
, mCompressionSessionRunning(false) |
|
|
|
|
, mPendingFrames(0) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -67,10 +64,8 @@ bool UBQuickTimeFile::init(const QString& pVideoFileName, const QString& pProfil |
|
|
|
|
, const QSize& pFrameSize, bool pRecordAudio, const QString& audioRecordingDevice) |
|
|
|
|
{ |
|
|
|
|
mFrameSize = pFrameSize; |
|
|
|
|
mFramesPerSecond = pFramesPerSecond; |
|
|
|
|
mVideoFileName = pVideoFileName; |
|
|
|
|
mRecordAudio = pRecordAudio; |
|
|
|
|
mSpatialQuality = pProfileData; |
|
|
|
|
|
|
|
|
|
if (mRecordAudio) |
|
|
|
|
mAudioRecordingDeviceName = audioRecordingDevice; |
|
|
|
@ -88,7 +83,6 @@ bool UBQuickTimeFile::init(const QString& pVideoFileName, const QString& pProfil |
|
|
|
|
void UBQuickTimeFile::run() |
|
|
|
|
{ |
|
|
|
|
mShouldStopCompression = false; |
|
|
|
|
mPendingFrames = 0; |
|
|
|
|
|
|
|
|
|
if (!beginSession()) |
|
|
|
|
return; |
|
|
|
@ -97,6 +91,7 @@ void UBQuickTimeFile::run() |
|
|
|
|
emit compressionSessionStarted(); |
|
|
|
|
|
|
|
|
|
do { |
|
|
|
|
// Video |
|
|
|
|
frameQueueMutex.lock(); |
|
|
|
|
|
|
|
|
|
frameBufferNotEmpty.wait(&UBQuickTimeFile::frameQueueMutex); |
|
|
|
@ -118,6 +113,7 @@ void UBQuickTimeFile::run() |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
frameQueueMutex.unlock(); |
|
|
|
|
|
|
|
|
|
} while(!mShouldStopCompression); |
|
|
|
|
|
|
|
|
|
endSession(); |
|
|
|
@ -257,7 +253,7 @@ bool UBQuickTimeFile::beginSession() |
|
|
|
|
void UBQuickTimeFile::endSession() |
|
|
|
|
{ |
|
|
|
|
[mVideoWriterInput markAsFinished]; |
|
|
|
|
bool success = [mVideoWriter finishWriting]; |
|
|
|
|
[mVideoWriter finishWritingWithCompletionHandler:^{}]; |
|
|
|
|
|
|
|
|
|
[mAdaptor release]; |
|
|
|
|
[mVideoWriterInput release]; |
|
|
|
@ -375,17 +371,27 @@ void UBQuickTimeFile::appendAudioBuffer(void* pBuffer, |
|
|
|
|
&sampleBuffer); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Add the audio sample to the asset writer input |
|
|
|
|
if ([mAudioWriterInput isReadyForMoreMediaData]) |
|
|
|
|
// Wait until the AssetWriterInput is ready, but no more than 100ms |
|
|
|
|
// (bit of a duct tape solution; cleaner solution would be to use a QQueue, |
|
|
|
|
// similar to the VideoWriter) |
|
|
|
|
int waitTime = 0; |
|
|
|
|
while(![mAudioWriterInput isReadyForMoreMediaData] && waitTime < 100) { |
|
|
|
|
waitTime += 10; |
|
|
|
|
usleep(10000); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ([mAudioWriterInput isReadyForMoreMediaData]) { |
|
|
|
|
if(![mAudioWriterInput appendSampleBuffer:sampleBuffer]) |
|
|
|
|
setLastErrorMessage(QString("Failed to append sample buffer to audio input")); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
setLastErrorMessage(QString("Audio Writer not ready; sample dropped")); |
|
|
|
|
setLastErrorMessage(QString("AudioWriterInput not ready. Buffer dropped.")); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CFRelease(sampleBuffer); |
|
|
|
|
CFRelease(blockBuffer); |
|
|
|
|
|
|
|
|
|
// The audioQueueBuffers are all freed when UBAudioQueueRecorder::close() is called |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|