summaryrefslogtreecommitdiff
path: root/rotord/ofxMovieExporter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'rotord/ofxMovieExporter.cpp')
-rw-r--r--rotord/ofxMovieExporter.cpp302
1 files changed, 81 insertions, 221 deletions
diff --git a/rotord/ofxMovieExporter.cpp b/rotord/ofxMovieExporter.cpp
index f7c47de..8b97813 100644
--- a/rotord/ofxMovieExporter.cpp
+++ b/rotord/ofxMovieExporter.cpp
@@ -32,47 +32,42 @@
#include "ofxMovieExporter.h"
//#include "ofThread.h"
-namespace itg
-{
- const std::string ofxMovieExporter::FILENAME_PREFIX = "capture";
- const std::string ofxMovieExporter::CONTAINER = "mp4";
-
- ofxMovieExporter::ofxMovieExporter() {
- outputFormat = NULL;
- formatCtx = NULL;
- videoStream = NULL;
-
- codec = NULL;
- codecCtx = NULL;
- convertCtx = NULL;
-
- inPixels = NULL;
- outPixels = NULL;
- encodedBuf = NULL;
-
- inFrame = NULL;
- outFrame = NULL;
-
- posX = 0;
- posY = 0;
- //inW = ofGetWidth();
- //inH = ofGetHeight();
- //outW = ofGetWidth();
- //outH = ofGetHeight();
-
- bool usePixelSource = false;
- pixelSource = NULL;
- }
-
- void ofxMovieExporter::setup(
- int outW,
- int outH,
- int bitRate,
- int frameRate,
- AVCodecID codecId,
- std::string container)
- {
- if (outW % 2 == 1 || outH % 2 == 1) //ofLog(OF_LOG_ERROR, "ofxMovieExporter: Resolution must be a multiple of 2");
+ const std::string ofxMovieExporter::FILENAME_PREFIX = "capture";
+ const std::string ofxMovieExporter::CONTAINER = "mp4";
+
+ ofxMovieExporter::ofxMovieExporter() {
+ outputFormat = NULL;
+ formatCtx = NULL;
+ videoStream = NULL;
+
+ codec = NULL;
+ codecCtx = NULL;
+ convertCtx = NULL;
+
+ inPixels = NULL;
+ outPixels = NULL;
+ encodedBuf = NULL;
+
+ inFrame = NULL;
+ outFrame = NULL;
+
+ // do one time encoder set up
+ av_register_all();
+
+ }
+
+ bool ofxMovieExporter::setup(
+ int outW,
+ int outH,
+ int bitRate,
+ int frameRate,
+ AVCodecID codecId,
+ std::string container)
+ {
+ if (outW % 2 == 1 || outH % 2 == 1) {
+ cerr << "ofxMovieExporter: Resolution must be a multiple of 2" << endl;
+ return false;
+ }
this->outW = outW;
this->outH = outH;
@@ -86,15 +81,17 @@ namespace itg
// HACK HACK HACK
// Time not syncing
// probably related to codec ticks_per_frame
- frameInterval /= 3.f;
+ //frameInterval /= 3.f;
+
recording = false;
numCaptures = 0;
- // do one time encoder set up
- av_register_all();
+
convertCtx = sws_getContext(inW, inH, PIX_FMT_RGB24, outW, outH, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
allocateMemory();
+
+ return true;
}
ofxMovieExporter::~ofxMovieExporter()
@@ -105,14 +102,14 @@ namespace itg
clearMemory();
}
- void ofxMovieExporter::record(std::string filePrefix, std::string folderPath)
+ bool ofxMovieExporter::record(std::string filePrefix, std::string folderPath)
{
initEncoder();
std::ostringstream oss;
oss << folderPath;
if (folderPath != "" && (folderPath[folderPath.size()-1] != '/' && folderPath[folderPath.size()-1] != '\\'))
- oss << "/";
+ oss << "/";
oss << filePrefix << numCaptures << "." << container;
outFileName = oss.str();
@@ -120,72 +117,36 @@ namespace itg
//if (url_fopen(&formatCtx->pb, outFileName.c_str(), 'wb' ) < 0) //url_fopen URL_WRONLY
// ofLog(OF_LOG_ERROR, "ofxMovieExporter: Could not open file %s", outFileName.c_str());
if (avio_open(&formatCtx->pb, outFileName.c_str(), AVIO_FLAG_WRITE) < 0) {
-
cerr << "ofxMovieExporter: Could not open file "<< outFileName<<endl;
+ return false;
}
//ofAddListener(ofEvents.draw, this, &ofxMovieExporter::checkFrame);
AVDictionary *options; //= NULL; causes a forward declaration error!?
- options=NULL;
+ options=NULL;
// write the stream header, if any
avformat_write_header(formatCtx,&options);
lastFrameTime = 0;
frameNum = 0;
recording = true;
-//#ifdef _THREAD_CAPTURE
-// startThread(true, false);
-//#endif
+
+ return true;
}
void ofxMovieExporter::stop()
{
- //ofRemoveListener(ofEvents.draw, this, &ofxMovieExporter::checkFrame);
+
recording = false;
numCaptures++;
-//#ifndef _THREAD_CAPTURE
-// finishRecord();
-//#endif
- }
- void ofxMovieExporter::setRecordingArea(int x, int y, int w, int h)
- {
- posX = x;
- posY = y;
- inW = w;
- inH = h;
- }
-
- void ofxMovieExporter::setRecordingArea(int rect)
- {
- /*
- posX = rect.x;
- posY = rect.y;
- inW = rect.width;
- inH = rect.height;
- */
- }
-
- void ofxMovieExporter::resetRecordingArea()
- {
- posX = 0;
- posY = 0;
- //inW = ofGetViewportWidth();
- //inH = ofGetViewportHeight();
- }
-
- int ofxMovieExporter::getRecordingArea()
- {
- return 0; //ofRectangle(posX, posY, inW, inH);
}
void ofxMovieExporter::setPixelSource(unsigned char* pixels, int w, int h)
{
- if (isRecording())
- stop();
-
+
if (pixels == NULL)
{
//ofLog(OF_LOG_ERROR, "ofxMovieExporter: Could not set NULL pixel source");
@@ -200,17 +161,7 @@ namespace itg
setup(outW, outH, bitRate, frameRate, codecId, container);
}
- void ofxMovieExporter::resetPixelSource()
- {
- usePixelSource = false;
- pixelSource = NULL;
- //inW = ofGetViewportWidth();
- //inH = ofGetViewportHeight();
-
- // resetup encoder etc
- setup(outW, outH, bitRate, frameRate, codecId, container);
- }
-
+
int ofxMovieExporter::getNumCaptures()
{
return numCaptures;
@@ -220,7 +171,7 @@ namespace itg
{
numCaptures = 0;
}
-
+
// PRIVATE
void ofxMovieExporter::finishRecord()
@@ -239,105 +190,38 @@ namespace itg
//url_fclose(formatCtx->pb);
}
-/*
-#ifdef _THREAD_CAPTURE
- void ofxMovieExporter::threadedFunction()
+ void ofxMovieExporter::encodeFrame()
{
- while (isThreadRunning())
- {
- if (!frameQueue.empty())
- {
- float start = ofGetElapsedTimef();
- frameQueueMutex.lock();
- inPixels = frameQueue.front();
- frameQueue.pop_front();
- frameQueueMutex.unlock();
-
- encodeFrame();
-
- frameMemMutex.lock();
- frameMem.push_back(inPixels);
- frameMemMutex.unlock();
- if (ofGetElapsedTimef() - start < frameInterval) ofSleepMillis(1000.f * (frameInterval - (ofGetElapsedTimef() - start)));
- }
- else if (!recording)
- {
- finishRecord();
- stopThread(true);
- }
- }
- }
-#endif
-*/
+
+ avpicture_fill((AVPicture*)inFrame, inPixels, PIX_FMT_RGB24, inW, inH);
+ avpicture_fill((AVPicture*)outFrame, outPixels, PIX_FMT_YUV420P, outW, outH);
+
+ //perform the conversion for RGB to YUV and size
+ sws_scale(convertCtx, inFrame->data, inFrame->linesize, 0, inH, outFrame->data, outFrame->linesize);
- void ofxMovieExporter::checkFrame() //ofEventArgs& args)
- {
- if (1) //ofGetElapsedTimef() - lastFrameTime >= frameInterval)
+ int outSize = avcodec_encode_video(codecCtx, encodedBuf, ENCODED_FRAME_BUFFER_SIZE, outFrame);
+ if (outSize > 0)
{
-/*
-#ifdef _THREAD_CAPTURE
- unsigned char* pixels;
- if (!frameMem.empty())
- {
- frameMemMutex.lock();
- pixels = frameMem.back();
- frameMem.pop_back();
- frameMemMutex.unlock();
- }
- else
- {
- pixels = new unsigned char[inW * inH * 3];
- }
-
- if (!usePixelSource)
- {
- // this part from ofImage::saveScreen
- int screenHeight = ofGetViewportHeight(); // if we are in a FBO or other viewport, this fails: ofGetHeight();
- int screenY = screenHeight - posY;
- screenY -= inH; // top, bottom issues
-
- glReadPixels(posX, screenY, inW, inH, GL_RGB, GL_UNSIGNED_BYTE, pixels);
- }
- else
- {
- memcpy(pixels, pixelSource, inW * inH * 3);
- }
-
- frameQueueMutex.lock();
- frameQueue.push_back(pixels);
- frameQueueMutex.unlock();
-#else
-*/
- if (!usePixelSource) {
- // this part from ofImage::saveScreen
- //int screenHeight = ofGetViewportHeight(); // if we are in a FBO or other viewport, this fails: ofGetHeight();
- //int screenY = screenHeight - posY;
- //screenY -= inH; // top, bottom issues
-
- //glReadPixels(posX, screenY, inW, inH, GL_RGB, GL_UNSIGNED_BYTE, inPixels);
- }
- else
- {
- memcpy(inPixels, pixelSource, inW * inH * 3);
- }
- encodeFrame();
-//#endif
- //lastFrameTime = ofGetElapsedTimef();
+ AVPacket pkt;
+ av_init_packet(&pkt);
+ //pkt.pts = av_rescale_q(codecCtx->coded_frame->pts, codecCtx->time_base, videoStream->time_base);
+ //if(codecCtx->coded_frame->key_frame) pkt.flags |= AV_PKT_FLAG_KEY;
+ pkt.pts = frameNum;//ofGetFrameNum();//codecCtx->coded_frame->pts;
+ pkt.flags |= AV_PKT_FLAG_KEY;
+ pkt.dts = pkt.pts;
+ pkt.stream_index = videoStream->index;
+ pkt.data = encodedBuf;
+ pkt.size = outSize;
+ av_write_frame(formatCtx, &pkt);
}
+ frameNum++;
}
- void ofxMovieExporter::encodeFrame()
+ void ofxMovieExporter::encodeFrame(char *pixels)
{
- avpicture_fill((AVPicture*)inFrame, inPixels, PIX_FMT_RGB24, inW, inH);
+ avpicture_fill((AVPicture*)inFrame, pixels, PIX_FMT_RGB24, inW, inH);
avpicture_fill((AVPicture*)outFrame, outPixels, PIX_FMT_YUV420P, outW, outH);
-
- // intentionally flip the image to compensate for OF flipping if reading from the screen
- if (!usePixelSource)
- {
- inFrame->data[0] += inFrame->linesize[0] * (inH - 1);
- inFrame->linesize[0] = -inFrame->linesize[0];
- }
//perform the conversion for RGB to YUV and size
sws_scale(convertCtx, inFrame->data, inFrame->linesize, 0, inH, outFrame->data, outFrame->linesize);
@@ -365,17 +249,7 @@ namespace itg
// clear if we need to reallocate
if(inPixels)
clearMemory();
-/*
- // allocate input stuff
-#ifdef _THREAD_CAPTURE
- //unsigned char* initFrameMem = new unsigned char[inW * inH * 3 * INIT_QUEUE_SIZE];
- for (int i = 0; i < INIT_QUEUE_SIZE; i++)
- {
- //frameMem.push_back(initFrameMem + inW * inH * 3 * i);
- frameMem.push_back(new unsigned char[inW * inH * 3]);
- }
-#else
-*/
+
inPixels = new unsigned char[inW * inH * 3];
//#endif
inFrame = avcodec_alloc_frame();
@@ -389,21 +263,7 @@ namespace itg
}
void ofxMovieExporter::clearMemory() {
-/*
- // clear input stuff
-#ifdef _THREAD_CAPTURE
- for (int i = 0; i < frameMem.size(); i++)
- {
- delete[] frameMem[i];
- }
- for (int i = 0; i < frameQueue.size(); i++)
- {
- delete[] frameQueue[i];
- }
-#else
-*/
delete[] inPixels;
-//#endif
inPixels = NULL;
@@ -464,11 +324,11 @@ namespace itg
/* needed to avoid using macroblocks in which some coeffs overflow
this doesnt happen with normal video, it just happens here as the
motion of the chroma plane doesnt match the luma plane */
- codecCtx->mb_decision=2;
- }
+ codecCtx->mb_decision=2;
+ }
// some formats want stream headers to be seperate
- if(!strcmp(formatCtx->oformat->name, "mp4") || !strcmp(formatCtx->oformat->name, "mov") || !strcmp(formatCtx->oformat->name, "3gp"))
- codecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
+ if(!strcmp(formatCtx->oformat->name, "mp4") || !strcmp(formatCtx->oformat->name, "mov") || !strcmp(formatCtx->oformat->name, "3gp"))
+ codecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
// set the output parameters (must be done even if no parameters).
//if (
@@ -485,10 +345,10 @@ namespace itg
// < 0) ofLog(OF_LOG_ERROR, "ofxMovieExproter: Could not set format parameters");
AVDictionary *options; //= NULL; causes a forward declaration error!?
- options=NULL;
+ options=NULL;
// open codec
//if (
avcodec_open2(codecCtx, codec,&options);
// < 0) ofLog(OF_LOG_ERROR, "ofxMovieExproter: Could not open codec");
}
-}
+