Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
O
OpenBoard
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lifo
Nicolas Ollinger
OpenBoard
Commits
ab4ae943
Commit
ab4ae943
authored
Nov 20, 2015
by
agriche
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev' of
https://github.com/DIP-SEM/OpenBoard
into dev
parents
7ad77bb4
642d1546
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
348 additions
and
748 deletions
+348
-748
OpenBoard.pro
OpenBoard.pro
+2
-2
UBPodcastController.cpp
src/podcast/UBPodcastController.cpp
+7
-7
podcast.pri
src/podcast/podcast.pri
+35
-34
UBAudioQueueRecorder.cpp
src/podcast/quicktime/UBAudioQueueRecorder.cpp
+2
-2
UBQuickTimeFile.cpp
src/podcast/quicktime/UBQuickTimeFile.cpp
+0
-656
UBQuickTimeFile.h
src/podcast/quicktime/UBQuickTimeFile.h
+31
-46
UBQuickTimeFile.mm
src/podcast/quicktime/UBQuickTimeFile.mm
+262
-0
UBQuickTimeVideoEncoder.cpp
src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp
+9
-1
No files found.
OpenBoard.pro
View file @
ab4ae943
...
...
@@ -130,13 +130,13 @@ macx {
LIBS += -framework Foundation
LIBS += -framework Cocoa
LIBS += -framework Carbon
LIBS += -framework AVFoundation
LIBS += -framework CoreMedia
LIBS += -lcrypto
CONFIG(release, debug|release):CONFIG += x86_64
CONFIG(debug, debug|release):CONFIG += x86_64
# TODO Craig: switch to 64bit
QMAKE_MAC_SDK = macosx
QMAKE_MACOSX_DEPLOYMENT_TARGET = "10.10"
...
...
src/podcast/UBPodcastController.cpp
View file @
ab4ae943
...
...
@@ -59,9 +59,9 @@
#ifdef Q_OS_WIN
#include "windowsmedia/UBWindowsMediaVideoEncoder.h"
#include "windowsmedia/UBWaveRecorder.h"
//
#elif defined(Q_OS_OSX)
//
#include "quicktime/UBQuickTimeVideoEncoder.h"
//
#include "quicktime/UBAudioQueueRecorder.h"
#elif defined(Q_OS_OSX)
#include "quicktime/UBQuickTimeVideoEncoder.h"
#include "quicktime/UBAudioQueueRecorder.h"
#endif
#include "core/memcheck.h"
...
...
@@ -305,8 +305,8 @@ 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
#elif defined(Q_OS_OSX)
mVideoEncoder
=
new
UBQuickTimeVideoEncoder
(
this
);
//deleted on stop
#endif
if
(
mVideoEncoder
)
...
...
@@ -795,8 +795,8 @@ QStringList UBPodcastController::audioRecordingDevices()
#ifdef Q_OS_WIN
devices
=
UBWaveRecorder
::
waveInDevices
();
//
#elif defined(Q_OS_OSX)
//
devices = UBAudioQueueRecorder::waveInDevices();
#elif defined(Q_OS_OSX)
devices
=
UBAudioQueueRecorder
::
waveInDevices
();
#endif
return
devices
;
...
...
src/podcast/podcast.pri
View file @
ab4ae943
HEADERS += src/podcast/UBPodcastController.h \
src/podcast/UBAbstractVideoEncoder.h \
src/podcast/UBPodcastRecordingPalette.h \
src/podcast/youtube/UBYouTubePublisher.h \
src/podcast/intranet/UBIntranetPodcastPublisher.h
SOURCES += src/podcast/UBPodcastController.cpp \
src/podcast/UBAbstractVideoEncoder.cpp \
src/podcast/UBPodcastRecordingPalette.cpp \
src/podcast/youtube/UBYouTubePublisher.cpp \
src/podcast/intranet/UBIntranetPodcastPublisher.cpp
win32 {
SOURCES += src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.cpp \
src/podcast/windowsmedia/UBWindowsMediaFile.cpp \
src/podcast/windowsmedia/UBWaveRecorder.cpp
HEADERS += src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.h \
src/podcast/windowsmedia/UBWindowsMediaFile.h \
src/podcast/windowsmedia/UBWaveRecorder.h
}
#macx {
# SOURCES += src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp \
# src/podcast/quicktime/UBQuickTimeFile.cpp \
# src/podcast/quicktime/UBAudioQueueRecorder.cpp
# HEADERS += src/podcast/quicktime/UBQuickTimeVideoEncoder.h \
# src/podcast/quicktime/UBQuickTimeFile.h \
# src/podcast/quicktime/UBAudioQueueRecorder.h
#}
HEADERS += src/podcast/UBPodcastController.h \
src/podcast/UBAbstractVideoEncoder.h \
src/podcast/UBPodcastRecordingPalette.h \
src/podcast/youtube/UBYouTubePublisher.h \
src/podcast/intranet/UBIntranetPodcastPublisher.h
SOURCES += src/podcast/UBPodcastController.cpp \
src/podcast/UBAbstractVideoEncoder.cpp \
src/podcast/UBPodcastRecordingPalette.cpp \
src/podcast/youtube/UBYouTubePublisher.cpp \
src/podcast/intranet/UBIntranetPodcastPublisher.cpp
win32 {
SOURCES += src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.cpp \
src/podcast/windowsmedia/UBWindowsMediaFile.cpp \
src/podcast/windowsmedia/UBWaveRecorder.cpp
HEADERS += src/podcast/windowsmedia/UBWindowsMediaVideoEncoder.h \
src/podcast/windowsmedia/UBWindowsMediaFile.h \
src/podcast/windowsmedia/UBWaveRecorder.h
}
macx {
SOURCES += src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp \
src/podcast/quicktime/UBAudioQueueRecorder.cpp
HEADERS += src/podcast/quicktime/UBQuickTimeVideoEncoder.h \
src/podcast/quicktime/UBQuickTimeFile.h \
src/podcast/quicktime/UBAudioQueueRecorder.h
OBJECTIVE_SOURCES += src/podcast/quicktime/UBQuickTimeFile.mm
}
src/podcast/quicktime/UBAudioQueueRecorder.cpp
View file @
ab4ae943
...
...
@@ -151,10 +151,10 @@ QString UBAudioQueueRecorder::deviceUIDFromDeviceID(AudioDeviceID id)
{
char
*
cname
=
new
char
[
1024
];
CFStringGetCString
(
name
,
cname
,
1024
,
kCFStringEncoding
ASCII
);
CFStringGetCString
(
name
,
cname
,
1024
,
kCFStringEncoding
ISOLatin1
);
int
length
=
CFStringGetLength
(
name
);
uid
=
QString
::
from
Ascii
(
cname
,
length
);
uid
=
QString
::
from
Latin1
(
cname
,
length
);
delete
cname
;
...
...
src/podcast/quicktime/UBQuickTimeFile.cpp
deleted
100644 → 0
View file @
7ad77bb4
This diff is collapsed.
Click to expand it.
src/podcast/quicktime/UBQuickTimeFile.h
View file @
ab4ae943
...
...
@@ -30,12 +30,29 @@
#include <QtCore>
#include <ApplicationServices/ApplicationServices.h>
#include <QuickTime/QuickTime.h>
#include <AudioToolbox/AudioToolbox.h>
#include <CoreVideo/CoreVideo.h>
#include "UBAudioQueueRecorder.h"
// Trick to get around the fact that the C++ compiler doesn't
// like Objective C code.
#ifdef __OBJC__ // defined by the Objective C compiler
@
class
AVAssetWriter
;
@
class
AVAssetWriterInput
;
@
class
AVAssetWriterInputPixelBufferAdaptor
;
typedef
AVAssetWriter
*
AssetWriterPTR
;
typedef
AVAssetWriterInput
*
AssetWriterInputPTR
;
typedef
AVAssetWriterInputPixelBufferAdaptor
*
AssetWriterInputAdaptorPTR
;
#else
typedef
void
*
AssetWriterPTR
;
typedef
void
*
AssetWriterInputPTR
;
typedef
void
*
AssetWriterInputAdaptorPTR
;
#endif
class
UBQuickTimeFile
:
public
QThread
{
Q_OBJECT
;
...
...
@@ -52,15 +69,11 @@ class UBQuickTimeFile : public QThread
CVPixelBufferRef
newPixelBuffer
();
bool
isCompressionSessionRunning
()
{
return
mCompressionSessionRunning
;
}
bool
isCompressionSessionRunning
()
{
return
mCompressionSessionRunning
;
}
QString
lastErrorMessage
()
const
{
return
mLastErrorMessage
;
}
QString
lastErrorMessage
()
const
{
return
mLastErrorMessage
;
}
void
endSession
();
struct
VideoFrame
{
...
...
@@ -79,47 +92,19 @@ class UBQuickTimeFile : public QThread
protected
:
void
run
();
private
slots
:
void
appendAudioBuffer
(
void
*
pBuffer
,
long
pLength
,
int
inNumberPacketDescriptions
,
const
AudioStreamPacketDescription
*
inPacketDescs
);
private
:
static
OSStatus
addEncodedFrameToMovie
(
void
*
encodedFrameOutputRefCon
,
ICMCompressionSessionRef
session
,
OSStatus
err
,
ICMEncodedFrameRef
encodedFrame
,
void
*
reserved
);
bool
beginSession
();
void
appendVideoFrame
(
CVPixelBufferRef
pixelBuffer
,
long
msTimeStamp
);
void
addEncodedFrame
(
ICMEncodedFrameRef
encodedFrame
,
OSStatus
err
);
bool
createCompressionSession
();
bool
closeCompressionSession
();
bool
createMovie
();
bool
createVideoMedia
();
bool
createAudioMedia
();
void
setLastErrorMessage
(
const
QString
&
error
);
bool
flushPendingFrames
();
ICMCompressionSessionRef
mVideoCompressionSession
;
Media
mVideoMedia
;
Media
mSoundMedia
;
Track
mVideoOutputTrack
;
Track
mSoundOutputTrack
;
volatile
CVPixelBufferPoolRef
mCVPixelBufferPool
;
SoundDescriptionHandle
mSoundDescription
;
Movie
mOutputMovie
;
DataHandler
mOutputMovieDataHandler
;
int
mFramesPerSecond
;
QSize
mFrameSize
;
...
...
@@ -130,17 +115,17 @@ class UBQuickTimeFile : public QThread
QString
mLastErrorMessage
;
AudioStreamBasicDescription
mAudioDataFormat
;
QPointer
<
UBAudioQueueRecorder
>
mWaveRecorder
;
QString
mSpatialQuality
;
CodecQ
mSpatialQuality
;
volatile
bool
mSouldStopCompression
;
volatile
bool
mShouldStopCompression
;
volatile
bool
mCompressionSessionRunning
;
QString
mAudioRecordingDeviceName
;
volatile
int
mPendingFrames
;
AssetWriterPTR
mVideoWriter
;
AssetWriterInputPTR
mVideoWriterInput
;
AssetWriterInputAdaptorPTR
mAdaptor
;
};
#endif
/* UBQUICKTIMEFILE_H_ */
src/podcast/quicktime/UBQuickTimeFile.mm
0 → 100644
View file @
ab4ae943
/*
* Copyright (C) 2013 Open Education Foundation
*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour
* l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of OpenBoard.
*
* OpenBoard is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License,
* with a specific linking exception for the OpenSSL project's
* "OpenSSL" library (or with modified versions of it that use the
* same license as the "OpenSSL" library).
*
* OpenBoard is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenBoard. If not, see <http://www.gnu.org/licenses/>.
*/
#include "UBQuickTimeFile.h"
#include <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#import <Foundation/Foundation.h>
#import <CoreMedia/CoreMedia.h>
#include "UBAudioQueueRecorder.h"
#include <QtGui>
#include "core/memcheck.h"
QQueue<UBQuickTimeFile::VideoFrame> UBQuickTimeFile::frameQueue;
QMutex UBQuickTimeFile::frameQueueMutex;
QWaitCondition UBQuickTimeFile::frameBufferNotEmpty;
UBQuickTimeFile::UBQuickTimeFile(QObject * pParent)
: QThread(pParent)
, mVideoWriter(0)
, mVideoWriterInput(0)
, mAdaptor(0)
, mCVPixelBufferPool(0)
, mFramesPerSecond(-1)
, mTimeScale(100)
, mRecordAudio(true)
, mShouldStopCompression(false)
, mCompressionSessionRunning(false)
, mPendingFrames(0)
{
// NOOP
}
UBQuickTimeFile::~UBQuickTimeFile()
{
// NOOP
}
bool UBQuickTimeFile::init(const QString& pVideoFileName, const QString& pProfileData, int pFramesPerSecond
, const QSize& pFrameSize, bool pRecordAudio, const QString& audioRecordingDevice)
{
mFrameSize = pFrameSize;
mFramesPerSecond = pFramesPerSecond;
mVideoFileName = pVideoFileName;
mRecordAudio = pRecordAudio;
mSpatialQuality = pProfileData;
if (mRecordAudio)
mAudioRecordingDeviceName = audioRecordingDevice;
else
mAudioRecordingDeviceName = "";
qDebug() << "UBQuickTimeFile created; video size: " << pFrameSize.width() << " x " << pFrameSize.height();
return true;
}
void UBQuickTimeFile::run()
{
mShouldStopCompression = false;
mPendingFrames = 0;
if (!beginSession())
return;
mCompressionSessionRunning = true;
emit compressionSessionStarted();
do {
frameQueueMutex.lock();
frameBufferNotEmpty.wait(&UBQuickTimeFile::frameQueueMutex);
if (!frameQueue.isEmpty()) {
QQueue<VideoFrame> localQueue = frameQueue;
frameQueue.clear();
frameQueueMutex.unlock();
while (!localQueue.isEmpty()) {
if ([mVideoWriterInput isReadyForMoreMediaData]) {
VideoFrame frame = localQueue.dequeue();
appendVideoFrame(frame.buffer, frame.timestamp);
}
else
usleep(10000);
}
}
else
frameQueueMutex.unlock();
} while(!mShouldStopCompression);
endSession();
}
/**
* \brief Initialize the AVAssetWriter, which handles writing the media to file
*/
bool UBQuickTimeFile::beginSession()
{
NSError *outError;
NSString * outputPath = [[NSString alloc] initWithUTF8String: mVideoFileName.toUtf8().data()];
NSURL * outputUrl = [[NSURL alloc] initFileURLWithPath: outputPath];
if (!outputUrl) {
qDebug() << "Podcast video URL invalid; not recording";
return false;
}
// Create and check the assetWriter
mVideoWriter = [[AVAssetWriter assetWriterWithURL:outputUrl
fileType:AVFileTypeQuickTimeMovie
error:&outError] retain];
NSCParameterAssert(mVideoWriter);
mVideoWriter.movieTimeScale = mTimeScale;
int frameWidth = mFrameSize.width();
int frameHeight = mFrameSize.height();
// Create the input and check it
NSDictionary * videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,
[NSNumber numberWithInt:frameWidth], AVVideoWidthKey,
[NSNumber numberWithInt:frameHeight], AVVideoHeightKey,
nil];
mVideoWriterInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoSettings] retain];
NSCParameterAssert(mVideoWriterInput);
// Pixel Buffer Adaptor. This makes it possible to pass CVPixelBuffers to the WriterInput
NSDictionary* pixelBufSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kCVPixelFormatType_32BGRA], kCVPixelBufferPixelFormatTypeKey,
[NSNumber numberWithInt: frameWidth], kCVPixelBufferWidthKey,
[NSNumber numberWithInt: frameHeight], kCVPixelBufferHeightKey,
nil];
mAdaptor = [[AVAssetWriterInputPixelBufferAdaptor
assetWriterInputPixelBufferAdaptorWithAssetWriterInput:mVideoWriterInput
sourcePixelBufferAttributes:pixelBufSettings] retain];
// Add the input(s) to the assetWriter
NSCParameterAssert([mVideoWriter canAddInput:mVideoWriterInput]);
[mVideoWriter addInput:mVideoWriterInput];
// begin the writing session
bool canStartWriting = [mVideoWriter startWriting];
[mVideoWriter startSessionAtSourceTime:CMTimeMake(0, mTimeScale)];
// return true if everything was created and started successfully
return (mVideoWriter != nil) && (mVideoWriterInput != nil) && canStartWriting;
}
/**
* \brief Close the recording sesion and finish writing the video file
*/
void UBQuickTimeFile::endSession()
{
[mVideoWriterInput markAsFinished];
bool success = [mVideoWriter finishWriting];
[mAdaptor release];
[mVideoWriterInput release];
[mVideoWriter release];
mAdaptor = nil;
mVideoWriterInput = nil;
mVideoWriter = nil;
}
/**
* \brief Request the recording to stop
*/
void UBQuickTimeFile::stop()
{
mShouldStopCompression = true;
}
/**
* \brief Create a CVPixelBufferRef from the input adaptor's CVPixelBufferPool
*/
CVPixelBufferRef UBQuickTimeFile::newPixelBuffer()
{
CVPixelBufferRef pixelBuffer = 0;
if(CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, mAdaptor.pixelBufferPool, &pixelBuffer) != kCVReturnSuccess)
{
setLastErrorMessage("Could not retrieve CV buffer from pool");
return 0;
}
return pixelBuffer;
}
/**
* \brief Add a frame to the pixel buffer adaptor
*/
void UBQuickTimeFile::appendVideoFrame(CVPixelBufferRef pixelBuffer, long msTimeStamp)
{
//qDebug() << "adding video frame at time: " << msTimeStamp;
CMTime t = CMTimeMake((msTimeStamp * mTimeScale / 1000.0), mTimeScale);
bool added = [mAdaptor appendPixelBuffer: pixelBuffer
withPresentationTime: t];
if (!added)
setLastErrorMessage(QString("Could not encode frame at time %1").arg(msTimeStamp));
CVPixelBufferRelease(pixelBuffer);
}
void UBQuickTimeFile::setLastErrorMessage(const QString& error)
{
mLastErrorMessage = error;
qWarning() << "UBQuickTimeFile error" << error;
}
src/podcast/quicktime/UBQuickTimeVideoEncoder.cpp
View file @
ab4ae943
...
...
@@ -130,6 +130,14 @@ void UBQuickTimeVideoEncoder::newPixmap(const QImage& pImage, long timestamp)
}
}
/**
* \brief Encode QImage into a video frame and add it to the UBQuickTimeFile's queue.
*
* This method retrieves the raw image from the supplied QImage, and uses memcpy to
* dump it into a CVPixelBuffer, obtained through the UBQuickTimeFile member. The
* pixel buffer, along with the timestamp, constitute a video frame which is added
* to the member UBQuickTimeFile's queue.
*/
void
UBQuickTimeVideoEncoder
::
encodeFrame
(
const
QImage
&
pImage
,
long
timestamp
)
{
Q_ASSERT
(
pImage
.
format
()
==
QImage
::
QImage
::
Format_RGB32
);
// <=> CVPixelBuffers / k32BGRAPixelFormat
...
...
@@ -157,7 +165,7 @@ void UBQuickTimeVideoEncoder::encodeFrame(const QImage& pImage, long timestamp)
const
uchar
*
imageBuffer
=
pImage
.
bits
();
memcpy
((
void
*
)
pixelBufferAddress
,
imageBuffer
,
pImage
.
numBytes
());
memcpy
((
void
*
)
pixelBufferAddress
,
imageBuffer
,
pImage
.
byteCount
());
CVPixelBufferUnlockBaseAddress
(
pixelBuffer
,
0
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment