コード例 #1
0
//--------------------------------------------------------------
bool ofxVideoRecorder::setupCustomOutput(int w, int h, float fps, int sampleRate, int channels, string outputString, bool sysClockSync, bool silent){
    if(bIsInitialized)
    {
        close();
    }

    bIsSilent = silent;
    bSysClockSync = sysClockSync;

    bRecordAudio = (sampleRate > 0 && channels > 0);
    bRecordVideo = (w > 0 && h > 0 && fps > 0);
    bFinishing = false;

    videoFramesRecorded = 0;
    audioSamplesRecorded = 0;

    if(!bRecordVideo && !bRecordAudio) {
        ofLogWarning() << "ofxVideoRecorder::setupCustomOutput(): invalid parameters, could not setup video or audio stream.\n"
        << "video: " << w << "x" << h << "@" << fps << "fps\n"
        << "audio: " << "channels: " << channels << " @ " << sampleRate << "Hz\n";
        return false;
    }
    videoPipePath = "";
    audioPipePath = "";
    pipeNumber = requestPipeNumber();
    if(bRecordVideo) {
        width = w;
        height = h;
        frameRate = fps;

        // recording video, create a FIFO pipe
        videoPipePath = ofFilePath::getAbsolutePath("ofxvrpipe" + ofToString(pipeNumber));
        if(!ofFile::doesFileExist(videoPipePath)){
            string cmd = "bash --login -c 'mkfifo " + videoPipePath + "'";
            system(cmd.c_str());
            // TODO: add windows compatable pipe creation (does ffmpeg work with windows pipes?)
        }
    }

    if(bRecordAudio) {
        this->sampleRate = sampleRate;
        audioChannels = channels;

        // recording video, create a FIFO pipe
        audioPipePath = ofFilePath::getAbsolutePath("ofxarpipe" + ofToString(pipeNumber));
        if(!ofFile::doesFileExist(audioPipePath)){
            string cmd = "bash --login -c 'mkfifo " + audioPipePath + "'";
            system(cmd.c_str());

            // TODO: add windows compatable pipe creation (does ffmpeg work with windows pipes?)
        }
    }

    stringstream cmd;
    // basic ffmpeg invocation, -y option overwrites output file
    cmd << "bash --login -c '" << ffmpegLocation << (bIsSilent?" -loglevel quiet ":" ") << "-y";
    if(bRecordAudio){
        cmd << " -acodec pcm_s16le -f s16le -ar " << sampleRate << " -ac " << audioChannels << " -i " << audioPipePath;
    }
    else { // no audio stream
        cmd << " -an";
    }
    if(bRecordVideo){ // video input options and file
        cmd << " -r "<< fps << " -s " << w << "x" << h << " -f rawvideo -pix_fmt " << pixelFormat <<" -i " << videoPipePath << " -r " << fps;
    }
    else { // no video stream
        cmd << " -vn";
    }
    cmd << " "+ outputString +"' &";

    //cerr << cmd.str();

    ffmpegThread.setup(cmd.str()); // start ffmpeg thread, will wait for input pipes to be opened

    if(bRecordAudio){
        audioThread.setup(audioPipePath, &audioFrames);
    }
    if(bRecordVideo){
        videoThread.setup(videoPipePath, &frames);
    }

    bIsInitialized = true;
    bIsRecording = false;
    bIsPaused = false;

    startTime = 0;
    recordingDuration = 0;
    totalRecordingDuration = 0;

    return bIsInitialized;
}
コード例 #2
0
bool ofxVideoRecorder::setupCustomOutput(int w, int h, float fps, int sampleRate, int channels, string outputString, bool sysClockSync, bool silent)
{
	if (bIsInitialized)
	{
		close();
	}

	bIsSilent = silent;
	bSysClockSync = sysClockSync;

	bRecordAudio = (sampleRate > 0 && channels > 0);
	bRecordVideo = (w > 0 && h > 0 && fps > 0);
	bFinishing = false;

	videoFramesRecorded = 0;
	audioSamplesRecorded = 0;

	if (!bRecordVideo && !bRecordAudio) {
		ofLogWarning() << "ofxVideoRecorder::setupCustomOutput(): invalid parameters, could not setup video or audio stream.\n"
			<< "video: " << w << "x" << h << "@" << fps << "fps\n"
			<< "audio: " << "channels: " << channels << " @ " << sampleRate << "Hz\n";
		return false;
	}
	videoPipePath = "";
	audioPipePath = "";
	pipeNumber = requestPipeNumber();
	if (bRecordVideo) {
		width = w;
		height = h;
		frameRate = fps;

#if defined( TARGET_OSX ) || defined( TARGET_LINUX )
		// recording video, create a FIFO pipe
		videoPipePath = ofFilePath::getAbsolutePath("ofxvrpipe" + ofToString(pipeNumber));

		ofStringReplace(videoPipePath, " ", "\\ ");

		if (!ofFile::doesFileExist(videoPipePath)) {
			string cmd = "bash --login -c 'mkfifo " + videoPipePath + "'";
			system(cmd.c_str());
		}
#endif
#ifdef TARGET_WIN32

		char vpip[128];
		int num = ofRandom(1024);
		sprintf(vpip, "\\\\.\\pipe\\videoPipe%d", num);
		vPipename = convertCharArrayToLPCWSTR(vpip);

		hVPipe = CreateNamedPipe(
			vPipename, // name of the pipe
			PIPE_ACCESS_OUTBOUND, // 1-way pipe -- send only
			PIPE_TYPE_BYTE, // send data as a byte stream
			1, // only allow 1 instance of this pipe
			0, // outbound buffer defaults to system default
			0, // no inbound buffer
			0, // use default wait time
			NULL // use default security attributes
			);

		if (!(hVPipe != INVALID_HANDLE_VALUE)) {
			if (GetLastError() != ERROR_PIPE_BUSY)
			{
				ofLogError("Video Pipe") << "Could not open video pipe.";
			}
			// All pipe instances are busy, so wait for 5 seconds. 
			if (!WaitNamedPipe(vPipename, 5000))
			{
				ofLogError("Video Pipe") << "Could not open video pipe: 5 second wait timed out.";
			}
		}

#endif
	}

	if (bRecordAudio) {
		this->sampleRate = sampleRate;
		audioChannels = channels;

#if defined( TARGET_OSX ) || defined( TARGET_LINUX )
		// recording video, create a FIFO pipe
		audioPipePath = ofFilePath::getAbsolutePath("ofxarpipe" + ofToString(pipeNumber));

		ofStringReplace(audioPipePath, " ", "\\ ");

		if (!ofFile::doesFileExist(audioPipePath)) {

			string cmd = "bash --login -c 'mkfifo " + audioPipePath + "'";
			system(cmd.c_str());
		}
#endif
#ifdef TARGET_WIN32


		char apip[128];
		int num = ofRandom(1024);
		sprintf(apip, "\\\\.\\pipe\\videoPipe%d", num);
		aPipename = convertCharArrayToLPCWSTR(apip);

		hAPipe = CreateNamedPipe(
			aPipename,
			PIPE_ACCESS_OUTBOUND, // 1-way pipe -- send only
			PIPE_TYPE_BYTE, // send data as a byte stream
			1, // only allow 1 instance of this pipe
			0, // outbound buffer defaults to system default
			0, // no inbound buffer
			0, // use default wait time
			NULL // use default security attributes
			);

		if (!(hAPipe != INVALID_HANDLE_VALUE)) {
			if (GetLastError() != ERROR_PIPE_BUSY)
			{
				ofLogError("Audio Pipe") << "Could not open audio pipe.";
			}
			// All pipe instances are busy, so wait for 5 seconds. 
			if (!WaitNamedPipe(aPipename, 5000))
			{
				ofLogError("Audio Pipe") << "Could not open pipe: 5 second wait timed out.";
			}
		}

#endif
	}

	stringstream cmd;
	// basic ffmpeg invocation, -y option overwrites output file
#if defined( TARGET_OSX ) || defined( TARGET_LINUX )
	cmd << "bash --login -c '" << ffmpegLocation << (bIsSilent ? " -loglevel quiet " : " ") << "-y";
	if (bRecordAudio) {
		cmd << " -acodec pcm_s16le -f s16le -ar " << sampleRate << " -ac " << audioChannels << " -i " << audioPipePath;
	}
	else { // no audio stream
		cmd << " -an";
	}
	if (bRecordVideo) { // video input options and file
		cmd << " -r " << fps << " -s " << w << "x" << h << " -f rawvideo -pix_fmt " << pixelFormat << " -i " << videoPipePath << " -r " << fps;
	}
	else { // no video stream
		cmd << " -vn";
	}
	cmd << " " + outputString + "' &";

	//cerr << cmd.str();

	ffmpegThread.setup(cmd.str()); // start ffmpeg thread, will wait for input pipes to be opened

	if (bRecordAudio) {
		audioThread.setup(audioPipePath, &audioFrames);
	}
	if (bRecordVideo) {
		videoThread.setup(videoPipePath, &frames);
	}
#endif
#ifdef TARGET_WIN32
	//evidently there are issues with multiple named pipes http://trac.ffmpeg.org/ticket/1663

	if (bRecordAudio && bRecordVideo) {
		bool fSuccess;

		// Audio Thread

		stringstream aCmd;
		aCmd << ffmpegLocation << " -y " << " -f s16le -acodec " << audioCodec << " -ar " << sampleRate << " -ac " << audioChannels;
		aCmd << " -i " << convertWideToNarrow(aPipename) << " -b:a " << audioBitrate << " " << outputString << "_atemp" << audioFileExt;

		ffmpegAudioThread.setup(aCmd.str());
		ofLogNotice("FFMpeg Command") << aCmd.str() << endl;

		fSuccess = ConnectNamedPipe(hAPipe, NULL);
		if (!fSuccess)
		{
			LPTSTR errorText = NULL;

			FormatMessageW(
				// use system message tables to retrieve error text
				FORMAT_MESSAGE_FROM_SYSTEM
				// allocate buffer on local heap for error text
				| FORMAT_MESSAGE_ALLOCATE_BUFFER
				// Important! will fail otherwise, since we're not 
				// (and CANNOT) pass insertion parameters
				| FORMAT_MESSAGE_IGNORE_INSERTS,
				NULL,    // unused with FORMAT_MESSAGE_FROM_SYSTEM
				GetLastError(),
				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
				(LPTSTR)&errorText,  // output 
				0, // minimum size for output buffer
				NULL);   // arguments - see note 
			wstring ws = errorText;
			string error(ws.begin(), ws.end());
			ofLogError("Audio Pipe") << "SetNamedPipeHandleState failed: " << error;
		}
		else {
			ofLogNotice("Audio Pipe") << "\n==========================\nAudio Pipe Connected Successfully\n==========================\n" << endl;
			audioThread.setup(hAPipe, &audioFrames);
		}

		// Video Thread

		stringstream vCmd;
		vCmd << ffmpegLocation << " -y " << " -r " << fps << " -s " << w << "x" << h << " -f rawvideo -pix_fmt " << pixelFormat;
		vCmd << " -i " << convertWideToNarrow(vPipename) << " -vcodec " << videoCodec << " -b:v " << videoBitrate << " " << outputString << "_vtemp" << movFileExt;

		ffmpegVideoThread.setup(vCmd.str());
		ofLogNotice("FFMpeg Command") << vCmd.str() << endl;

		fSuccess = ConnectNamedPipe(hVPipe, NULL);
		if (!fSuccess)
		{
			LPTSTR errorText = NULL;

			FormatMessageW(
				// use system message tables to retrieve error text
				FORMAT_MESSAGE_FROM_SYSTEM
				// allocate buffer on local heap for error text
				| FORMAT_MESSAGE_ALLOCATE_BUFFER
				// Important! will fail otherwise, since we're not 
				// (and CANNOT) pass insertion parameters
				| FORMAT_MESSAGE_IGNORE_INSERTS,
				NULL,    // unused with FORMAT_MESSAGE_FROM_SYSTEM
				GetLastError(),
				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
				(LPTSTR)&errorText,  // output 
				0, // minimum size for output buffer
				NULL);   // arguments - see note 
			wstring ws = errorText;
			string error(ws.begin(), ws.end());
			ofLogError("Video Pipe") << "SetNamedPipeHandleState failed: " << error;
		}
		else {
			ofLogNotice("Video Pipe") << "\n==========================\nVideo Pipe Connected Successfully\n==========================\n" << endl;
			videoThread.setup(hVPipe, &frames);
		}
	}
	else {
		cmd << ffmpegLocation << " -y ";
		if (bRecordAudio) {
			cmd << " -f s16le -acodec " << audioCodec << " -ar " << sampleRate << " -ac " << audioChannels << " -i " << convertWideToNarrow(aPipename);
		}
		else { // no audio stream
			cmd << " -an";
		}
		if (bRecordVideo) { // video input options and file
			cmd << " -r " << fps << " -s " << w << "x" << h << " -f rawvideo -pix_fmt " << pixelFormat << " -i " << convertWideToNarrow(vPipename);
		}
		else { // no video stream
			cmd << " -vn";
		}
		if (bRecordAudio)
			cmd << " -b:a " << audioBitrate;
		if (bRecordVideo)
			cmd << " -vcodec " << videoCodec << " -b:v " << videoBitrate;
		cmd << " " << outputString << movFileExt;

		ofLogNotice("FFMpeg Command") << cmd.str() << endl;

		ffmpegThread.setup(cmd.str()); // start ffmpeg thread, will wait for input pipes to be opened

		if (bRecordAudio) {
			//this blocks, so we have to call it after ffmpeg is listening for a pipe
			bool fSuccess = ConnectNamedPipe(hAPipe, NULL);
			if (!fSuccess)
			{
				LPTSTR errorText = NULL;

				FormatMessageW(
					// use system message tables to retrieve error text
					FORMAT_MESSAGE_FROM_SYSTEM
					// allocate buffer on local heap for error text
					| FORMAT_MESSAGE_ALLOCATE_BUFFER
					// Important! will fail otherwise, since we're not 
					// (and CANNOT) pass insertion parameters
					| FORMAT_MESSAGE_IGNORE_INSERTS,
					NULL,    // unused with FORMAT_MESSAGE_FROM_SYSTEM
					GetLastError(),
					MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
					(LPTSTR)&errorText,  // output 
					0, // minimum size for output buffer
					NULL);   // arguments - see note 
				wstring ws = errorText;
				string error(ws.begin(), ws.end());
				ofLogError("Audio Pipe") << "SetNamedPipeHandleState failed: " << error;
			}
			else {
				ofLogNotice("Audio Pipe") << "\n==========================\nAudio Pipe Connected Successfully\n==========================\n" << endl;
				audioThread.setup(hAPipe, &audioFrames);
			}
		}
		if (bRecordVideo) {
			//this blocks, so we have to call it after ffmpeg is listening for a pipe
			bool fSuccess = ConnectNamedPipe(hVPipe, NULL);
			if (!fSuccess)
			{
				LPTSTR errorText = NULL;

				FormatMessageW(
					// use system message tables to retrieve error text
					FORMAT_MESSAGE_FROM_SYSTEM
					// allocate buffer on local heap for error text
					| FORMAT_MESSAGE_ALLOCATE_BUFFER
					// Important! will fail otherwise, since we're not 
					// (and CANNOT) pass insertion parameters
					| FORMAT_MESSAGE_IGNORE_INSERTS,
					NULL,    // unused with FORMAT_MESSAGE_FROM_SYSTEM
					GetLastError(),
					MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
					(LPTSTR)&errorText,  // output 
					0, // minimum size for output buffer
					NULL);   // arguments - see note 
				wstring ws = errorText;
				string error(ws.begin(), ws.end());
				ofLogError("Video Pipe") << "SetNamedPipeHandleState failed: " << error;
			}
			else {
				ofLogNotice("Video Pipe") << "\n==========================\nVideo Pipe Connected Successfully\n==========================\n" << endl;
				videoThread.setup(hVPipe, &frames);
			}
		}

	}
#endif

	bIsInitialized = true;
	bIsRecording = false;
	bIsPaused = false;

	startTime = 0;
	recordingDuration = 0;
	totalRecordingDuration = 0;

	return bIsInitialized;
		}