diff options
Diffstat (limited to 'rotord/ofxMovieExporter.cpp')
| -rw-r--r-- | rotord/ofxMovieExporter.cpp | 302 |
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"); } -} + |
