264 lines
8.1 KiB
C
264 lines
8.1 KiB
C
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
//----------------------------------------------------------------------------------------
|
||
|
|
||
|
#ifndef QUICKTIME_RECORDER_H
|
||
|
#define QUICKTIME_RECORDER_H
|
||
|
|
||
|
#ifdef _WIN32
|
||
|
#pragma once
|
||
|
#endif
|
||
|
|
||
|
//--------------------------------------------------------------------------------
|
||
|
|
||
|
#if defined( OSX )
|
||
|
#include <quicktime/QTML.h>
|
||
|
#include <quicktime/Movies.h>
|
||
|
#include <quicktime/QuickTimeComponents.h>
|
||
|
#elif defined( WIN32 )
|
||
|
#include "QTML.h"
|
||
|
#include "Movies.h"
|
||
|
#include "QuickTimeComponents.h"
|
||
|
#else
|
||
|
#error "Quicktime encoding is not supported on this platform"
|
||
|
#endif
|
||
|
|
||
|
#include "video/ivideoservices.h"
|
||
|
|
||
|
#include "video_macros.h"
|
||
|
#include "quicktime_common.h"
|
||
|
|
||
|
|
||
|
// comment out to prevent logging of creation data
|
||
|
//#define LOG_ENCODER_OPERATIONS
|
||
|
//#define LOG_ENCODER_AUDIO_OPERATIONS
|
||
|
|
||
|
// comment out to log images of frames
|
||
|
//#define LOG_FRAMES_TO_TGA
|
||
|
//#define LOG_FRAMES_TO_TGA_INTERVAL 16
|
||
|
|
||
|
#if defined( LOG_ENCODER_OPERATIONS ) || defined( LOG_ENCODER_AUDIO_OPERATIONS ) || defined ( LOG_FRAMES_TO_TGA ) || defined ( ENABLE_EXTERNAL_ENCODER_LOGGING )
|
||
|
#include <filesystem.h>
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
// ------------------------------------------------------------------------
|
||
|
// CQTVideoFileComposer
|
||
|
// Class to manages to creation of a video file from a series of
|
||
|
// supplied bitmap images.
|
||
|
//
|
||
|
// At this time, the time interval between frames must be the same for all
|
||
|
// frames of the movie
|
||
|
// ------------------------------------------------------------------------
|
||
|
class CQTVideoFileComposer
|
||
|
{
|
||
|
public:
|
||
|
static const CodecType DEFAULT_CODEC = kH264CodecType;
|
||
|
static const CodecQ DEFAULT_ENCODE_QUALITY = codecNormalQuality;
|
||
|
static const Fixed DEFAULT_GAMMA = kQTUseSourceGammaLevel;
|
||
|
|
||
|
static const int MIN_AUDIO_SAMPLE_GROUP_SIZE = 64;
|
||
|
static const int MAX_AUDIO_GROUP_SIZE_IN_SEC = 4;
|
||
|
|
||
|
CQTVideoFileComposer();
|
||
|
~CQTVideoFileComposer();
|
||
|
|
||
|
bool CreateNewMovie( const char *fileName, bool hasAudio );
|
||
|
|
||
|
bool SetMovieVideoParameters( int width, int height, VideoFrameRate_t movieFPS, VideoEncodeCodec_t desiredCodec, int encodeQuality, VideoEncodeGamma_t gamma );
|
||
|
bool SetMovieSourceImageParameters( int srcWidth, int srcHeight, VideoEncodeSourceFormat_t srcImageFormat );
|
||
|
bool SetMovieSourceAudioParameters( AudioEncodeSourceFormat_t srcAudioFormat = AudioEncodeSourceFormat::AUDIO_NONE, int audioSampleRate = 0, AudioEncodeOptions_t audioOptions = AudioEncodeOptions::NO_AUDIO_OPTIONS, int audioSampleGroupSize = 0 );
|
||
|
|
||
|
bool AppendVideoFrameToMedia( void *ImageBuffer, int strideAdjustBytes );
|
||
|
bool AppendAudioSamplesToMedia( void *soundBuffer, size_t bufferSize );
|
||
|
|
||
|
bool AbortMovie();
|
||
|
bool FinishMovie( bool SaveMovieToDisk = true );
|
||
|
|
||
|
size_t GetFrameBufferSize() { return m_SrcImageSize; }
|
||
|
|
||
|
bool CheckFilename( const char *filename );
|
||
|
|
||
|
void SetResult( VideoResult_t status );
|
||
|
VideoResult_t GetResult();
|
||
|
bool IsReadyToRecord();
|
||
|
|
||
|
int GetFrameCount() { return m_nFramesAdded; }
|
||
|
int GetSampleCount() { return m_nSamplesAdded; }
|
||
|
|
||
|
VideoFrameRate_t GetFPS() { return m_MovieRecordFPS; }
|
||
|
int GetSampleRate() { return m_AudioSourceFrequency; }
|
||
|
|
||
|
bool HasAudio() { return m_bHasAudioTrack; }
|
||
|
|
||
|
#ifdef ENABLE_EXTERNAL_ENCODER_LOGGING
|
||
|
bool LogMessage( const char *msg );
|
||
|
#endif
|
||
|
|
||
|
private:
|
||
|
enum AudioGrouping_t
|
||
|
{
|
||
|
AG_NONE = 0,
|
||
|
AG_FIXED_SIZE,
|
||
|
AG_PER_FRAME
|
||
|
};
|
||
|
|
||
|
// disable copy constructor and copy assignment
|
||
|
CQTVideoFileComposer( CQTVideoFileComposer &rhs );
|
||
|
CQTVideoFileComposer& operator= ( CQTVideoFileComposer &rhs );
|
||
|
|
||
|
bool CheckForReadyness();
|
||
|
bool BeginMovieCreation();
|
||
|
bool EndMovieCreation( bool saveMovieData );
|
||
|
|
||
|
bool SyncAndFlushAudio();
|
||
|
int GetAudioSampleCountThruFrame( int frameNo );
|
||
|
|
||
|
VideoResult_t m_LastResult;
|
||
|
|
||
|
// Current State of Movie Creation;
|
||
|
bool m_bMovieCreated;
|
||
|
bool m_bHasAudioTrack;
|
||
|
|
||
|
bool m_bMovieConfigured;
|
||
|
bool m_bSourceImagesConfigured;
|
||
|
bool m_bSourceAudioConfigured;
|
||
|
|
||
|
bool m_bComposingMovie;
|
||
|
bool m_bMovieCompleted;
|
||
|
|
||
|
int m_nFramesAdded;
|
||
|
|
||
|
int m_nAudioFramesAdded;
|
||
|
int m_nSamplesAdded;
|
||
|
int m_nSamplesAddedToMedia;
|
||
|
|
||
|
// parameters of the movie to create;
|
||
|
int m_MovieFrameWidth;
|
||
|
int m_MovieFrameHeight;
|
||
|
|
||
|
VideoFrameRate_t m_MovieRecordFPS;
|
||
|
TimeScale m_MovieTimeScale;
|
||
|
TimeValue m_DurationPerFrame;
|
||
|
|
||
|
// Audio recording options
|
||
|
AudioEncodeOptions_t m_AudioOptions; // Option flags specifed by user
|
||
|
AudioGrouping_t m_SampleGrouping; // Mode to group samples
|
||
|
int m_nAudioSampleGroupSize; // number of samples to collect per sample group
|
||
|
|
||
|
int m_AudioSourceFrequency; // Source frequency of the supplied audio
|
||
|
int m_AudioBytesPerSample;
|
||
|
|
||
|
bool m_bBufferSourceAudio;
|
||
|
bool m_bLimitAudioDurationToVideo;
|
||
|
|
||
|
byte *m_srcAudioBuffer; // buffer to hold audio samples
|
||
|
size_t m_srcAudioBufferSize;
|
||
|
size_t m_srcAudioBufferCurrentSize;
|
||
|
|
||
|
int m_AudioSampleFrameCounter;
|
||
|
|
||
|
char *m_FileName;
|
||
|
|
||
|
int m_SrcImageWidth;
|
||
|
int m_SrcImageHeight;
|
||
|
size_t m_SrcImageSize;
|
||
|
int m_ScrImageMaxCompressedSize;
|
||
|
byte *m_SrcImageBuffer;
|
||
|
Handle m_SrcImageCompressedBuffer;
|
||
|
OSType m_SrcPixelFormat;
|
||
|
int m_SrcBytesPerPixel;
|
||
|
|
||
|
OSType m_GWorldPixelFormat;
|
||
|
int m_GWorldBytesPerPixel;
|
||
|
int m_GWorldImageWidth;
|
||
|
int m_GWorldImageHeight;
|
||
|
|
||
|
Handle m_srcSoundDescription;
|
||
|
|
||
|
|
||
|
// parameters used by QuickTime
|
||
|
CodecQ m_EncodeQuality;
|
||
|
CodecType m_VideoCodecToUse;
|
||
|
Fixed m_EncodeGamma;
|
||
|
|
||
|
Rect m_GWorldRect;
|
||
|
GWorldPtr m_theSrcGWorld;
|
||
|
|
||
|
// short m_ResRefNum; // QuickTime Movie Resource Ref number
|
||
|
|
||
|
Handle m_MovieFileDataRef;
|
||
|
OSType m_MovieFileDataRefType;
|
||
|
DataHandler m_MovieFileDataHandler;
|
||
|
|
||
|
|
||
|
Movie m_theMovie;
|
||
|
Track m_theVideoTrack;
|
||
|
Track m_theAudioTrack;
|
||
|
Media m_theVideoMedia;
|
||
|
Media m_theAudioMedia;
|
||
|
|
||
|
#ifdef LOG_ENCODER_OPERATIONS
|
||
|
FileHandle_t m_LogFile;
|
||
|
void LogMsg( PRINTF_FORMAT_STRING const char* pMsg, ... );
|
||
|
#endif
|
||
|
|
||
|
#ifdef LOG_FRAMES_TO_TGA
|
||
|
char m_TGAFileBase[MAX_PATH];
|
||
|
#endif
|
||
|
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
class CQuickTimeVideoRecorder : public IVideoRecorder
|
||
|
{
|
||
|
public:
|
||
|
CQuickTimeVideoRecorder();
|
||
|
~CQuickTimeVideoRecorder();
|
||
|
|
||
|
virtual bool EstimateMovieFileSize( size_t *pEstSize, int movieWidth, int movieHeight, VideoFrameRate_t movieFps, float movieDuration, VideoEncodeCodec_t theCodec, int videoQuality, AudioEncodeSourceFormat_t srcAudioFormat = AudioEncodeSourceFormat::AUDIO_NONE, int audioSampleRate = 0 );
|
||
|
|
||
|
virtual bool CreateNewMovieFile( const char *pFilename, bool hasAudioTrack = false );
|
||
|
|
||
|
virtual bool SetMovieVideoParameters( VideoEncodeCodec_t theCodec, int videoQuality, int movieFrameWidth, int movieFrameHeight, VideoFrameRate_t movieFPS, VideoEncodeGamma_t gamma = VideoEncodeGamma::NO_GAMMA_ADJUST );
|
||
|
virtual bool SetMovieSourceImageParameters( VideoEncodeSourceFormat_t srcImageFormat, int imgWidth, int imgHeight );
|
||
|
virtual bool SetMovieSourceAudioParameters( AudioEncodeSourceFormat_t srcAudioFormat = AudioEncodeSourceFormat::AUDIO_NONE, int audioSampleRate = 0, AudioEncodeOptions_t audioOptions = AudioEncodeOptions::NO_AUDIO_OPTIONS, int audioSampleGroupSize = 0 );
|
||
|
|
||
|
virtual bool IsReadyToRecord();
|
||
|
virtual VideoResult_t GetLastResult();
|
||
|
|
||
|
virtual bool AppendVideoFrame( void *pFrameBuffer, int nStrideAdjustBytes = 0 );
|
||
|
virtual bool AppendAudioSamples( void *pSampleBuffer, size_t sampleSize );
|
||
|
|
||
|
virtual int GetFrameCount();
|
||
|
virtual int GetSampleCount();
|
||
|
virtual int GetSampleRate();
|
||
|
virtual VideoFrameRate_t GetFPS();
|
||
|
|
||
|
virtual bool AbortMovie();
|
||
|
virtual bool FinishMovie( bool SaveMovieToDisk = true );
|
||
|
|
||
|
#ifdef ENABLE_EXTERNAL_ENCODER_LOGGING
|
||
|
virtual bool LogMessage( const char *msg );
|
||
|
#endif
|
||
|
|
||
|
private:
|
||
|
|
||
|
void SetResult( VideoResult_t resultCode );
|
||
|
|
||
|
float GetDataRate( int quality, int width, int height );
|
||
|
|
||
|
CQTVideoFileComposer *m_pEncoder;
|
||
|
VideoResult_t m_LastResult;
|
||
|
bool m_bHasAudio;
|
||
|
bool m_bMovieFinished;
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
#endif // QUICKTIME_RECORDER_H
|