summaryrefslogtreecommitdiff
path: root/rotord/ofxMovieExporter.cpp
diff options
context:
space:
mode:
authorTim Redfern <tim@eclectronics.org>2013-05-30 17:19:36 +0100
committerTim Redfern <tim@eclectronics.org>2013-05-30 17:19:36 +0100
commite7c0b4a70990a1293056de92b555743e378b06eb (patch)
tree30730e09de90b835c7dcebd44bad6f5899a7bb60 /rotord/ofxMovieExporter.cpp
parentf648d137d381d778f1ae25a25a2cc7257128123b (diff)
thread safety issues
Diffstat (limited to 'rotord/ofxMovieExporter.cpp')
-rwxr-xr-xrotord/ofxMovieExporter.cpp426
1 files changed, 0 insertions, 426 deletions
diff --git a/rotord/ofxMovieExporter.cpp b/rotord/ofxMovieExporter.cpp
deleted file mode 100755
index 15abfe2..0000000
--- a/rotord/ofxMovieExporter.cpp
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * ofxMovieExporter.cpp
- *
- * Copyright (c) 2011, Neil Mendoza, http://www.neilmendoza.com
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of 16b.it nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- */
-#include "ofxMovieExporter.h"
-//#include "ofThread.h"
-
- const std::string ofxMovieExporter::FILENAME_PREFIX = "capture";
- const std::string ofxMovieExporter::CONTAINER = "mov";
-
- 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;
- this->frameRate = frameRate;
- this->bitRate = bitRate;
- this->codecId = codecId;
- this->container = container;
-
- frameInterval = 1.f / (float)frameRate;
-
- // HACK HACK HACK
- // Time not syncing
- // probably related to codec ticks_per_frame
- //frameInterval /= 3.f;
-
- recording = false;
- numCaptures = 0;
-
- inW=outW;
- inH=outH;
-
- convertCtx = sws_getContext(inW, inH, PIX_FMT_RGB24, outW, outH, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
-
- allocateMemory();
-
- return true;
- }
-
- ofxMovieExporter::~ofxMovieExporter()
- {
- if (recording) finishRecord();
-
- //stopThread(true);
- clearMemory();
- }
-
- 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 << filePrefix << numCaptures << "." << container;
- outFileName = oss.str();
-
- // open the output file
- //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;
- // write the stream header, if any
- avformat_write_header(formatCtx,&options);
-
- lastFrameTime = 0;
- aframeNum = 0;
- vframeNum = 0;
- recording = true;
-
- return true;
- }
-
- void ofxMovieExporter::stop()
- {
-
- recording = false;
- numCaptures++;
-
- }
-
- void ofxMovieExporter::setPixelSource(unsigned char* pixels, int w, int h)
- {
-
- if (pixels == NULL)
- {
- //ofLog(OF_LOG_ERROR, "ofxMovieExporter: Could not set NULL pixel source");
- return;
- }
- pixelSource = pixels;
- inW = w;
- inH = h;
- usePixelSource = true;
-
- // resetup encoder etc
- setup(outW, outH, bitRate, frameRate, codecId, container);
- }
-
-
- int ofxMovieExporter::getNumCaptures()
- {
- return numCaptures;
- }
-
- void ofxMovieExporter::resetNumCaptures()
- {
- numCaptures = 0;
- }
-
-// PRIVATE
-
- void ofxMovieExporter::finishRecord()
- {
- av_write_trailer(formatCtx);
-
- // free the encoder
- avcodec_close(codecCtx);
- for(int i = 0; i < formatCtx->nb_streams; i++)
- {
- av_freep(&formatCtx->streams[i]->codec);
- av_freep(&formatCtx->streams[i]);
- }
- av_free(formatCtx);
- formatCtx = NULL;
- //url_fclose(formatCtx->pb);
- }
-
- void ofxMovieExporter::encodeFrame()
- {
-
- 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);
-
- int outSize = avcodec_encode_video(codecCtx, encodedBuf, ENCODED_FRAME_BUFFER_SIZE, outFrame);
- if (outSize > 0)
- {
- 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);
- }
-
- vframeNum++;
- }
-
- bool ofxMovieExporter::encodeFrame(unsigned char *pixels)
- {
-
- if (pixels==nullptr) return false;
-
- //is it possible to skip the first avpicture_fill?
-
- avpicture_fill((AVPicture*)inFrame, pixels, 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);
-
-
- AVPacket pkt;
- int outSize = avcodec_encode_video(codecCtx, encodedBuf, ENCODED_FRAME_BUFFER_SIZE, outFrame);
- if (outSize > 0)
- {
-
- av_init_packet(&pkt);
- pkt.pts = (int64_t)vframeNum*(frameInterval*(((float)videoStream->time_base.den)/videoStream->time_base.num));//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_interleaved_write_frame(formatCtx, &pkt);
-
- vframeNum++;
- }
-
-
- //is it as simple as writing an audio packet for every video packet?
- // avcodec_encode_audio2(AVCodecContext *avctx,AVPacket *avpkt,const AVFrame *frame,int *got_packet_ptr);
- AVPacket apkt;
- av_init_packet(&apkt);
- apkt.pts = (int64_t)aframeNum*(aframeInterval*(((float)videoStream->time_base.den)/videoStream->time_base.num));//ofGetFrameNum();//codecCtx->coded_frame->pts;
-
- while(apkt.pts<pkt.pts) {
- apkt.flags |= AV_PKT_FLAG_KEY;
- apkt.dts = apkt.pts;
- apkt.stream_index = audioStream->index;
- //apkt.data = encodedBuf;
- apkt.size = outSize;
-
- AVFrame* afrm=avcodec_alloc_frame();
- afrm->nb_samples=44100/25;
- afrm->format=AV_SAMPLE_FMT_S16;
- uint8_t *d=new uint8_t[afrm->nb_samples*2*2];
- afrm->data[0]=d;
-
- int gpp;
-
- //avcodec_fill_audio_frame(afrm, 2, AV_SAMPLE_FMT_S16,(uint8_t *)d,(44100/25) * 2 * 2,1);
-
- int audioOutSize = avcodec_encode_audio2(acodecCtx,&apkt,afrm,&gpp);
-
- av_interleaved_write_frame(formatCtx, &apkt);
-
- aframeNum++;
- apkt.pts = (int64_t)aframeNum*(aframeInterval*(((float)videoStream->time_base.den)/videoStream->time_base.num));//ofGetFrameNum();//codecCtx->coded_frame->pts;
- }
-
-
- return true;
- }
-
- void ofxMovieExporter::allocateMemory()
- {
- // clear if we need to reallocate
- if(inPixels)
- clearMemory();
-
- inPixels = new unsigned char[inW * inH * 3];
-//#endif
- inFrame = avcodec_alloc_frame();
-
- // allocate output stuff
- int outSize = avpicture_get_size(PIX_FMT_YUV420P, outW, outH);
- outPixels = (unsigned char*)av_malloc(outSize);
- outFrame = avcodec_alloc_frame();
-
- encodedBuf = (unsigned char*)av_malloc(ENCODED_FRAME_BUFFER_SIZE);
- }
-
- void ofxMovieExporter::clearMemory() {
- delete[] inPixels;
-
- inPixels = NULL;
-
- av_free(inFrame);
- av_free(outFrame);
- av_free(encodedBuf);
- av_free(outPixels);
-
- inFrame = NULL;
- outFrame = NULL;
- encodedBuf = NULL;
- outPixels = NULL;
- }
-
- void ofxMovieExporter::initEncoder()
- {
- /////////////////////////////////////////////////////////////
- // find codec
- codec = avcodec_find_encoder(codecId);
- //if (!codec) ofLog(OF_LOG_ERROR, "ofxMovieExporter: Codec not found");
-
-
-
- ////////////////////////////////////////////////////////////
- // auto detect the output format from the name. default is mpeg.
- ostringstream oss;
- oss << "amovie." << container;
- outputFormat = av_guess_format(NULL, oss.str().c_str(), NULL);
- //if (!outputFormat) ofLog(OF_LOG_ERROR, "ofxMovieExporter: Could not guess output container for an %s file (ueuur!!)", container.c_str());
- // set the format codec (the format also has a default codec that can be read from it)
- outputFormat->video_codec = codec->id;
-
- acodec = avcodec_find_encoder(outputFormat->audio_codec);
- //--------------------------->
- //leaving the audio codec at the default for now
- //--------------------------->
-
- /////////////////////////////////////////////////////////////
- // allocate the format context
- formatCtx = avformat_alloc_context();
- //if (!formatCtx) ofLog(OF_LOG_ERROR, "ofxMovieExporter: Could not allocate format context");
- formatCtx->oformat = outputFormat;
-
-
-
- /////////////////////////////////////////////////////////////
- // set up the video stream
- videoStream = avformat_new_stream(formatCtx,codec);
- //videoStream = av_new_stream(formatCtx, 0);
-
-
- /////////////////////////////////////////////////////////////
- // init codec context for video
- codecCtx = videoStream->codec;
- codecCtx->bit_rate = bitRate;
- codecCtx->width = outW;
- codecCtx->height = outH;
-
- codecCtx->time_base.num = 1;//codecCtx->ticks_per_frame;
- codecCtx->time_base.den = frameRate;
- videoStream->time_base = codecCtx->time_base;
- //audioStream->time_base = codecCtx->time_base; //???has the capability of crashing
-
- codecCtx->gop_size = 10; /* emit one intra frame every ten frames */
- codecCtx->pix_fmt = PIX_FMT_YUV420P;
-
- if (codecCtx->codec_id == CODEC_ID_MPEG1VIDEO)
- {
- /* 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;
- }
- // 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;
-
- // set the output parameters (must be done even if no parameters).
- //if (
- //
- //
- // ???????
-
- //av_set_parameters(formatCtx, NULL);
- //
- //
- //
- //
-
- // < 0) ofLog(OF_LOG_ERROR, "ofxMovieExproter: Could not set format parameters");
-
- AVDictionary *options; //= NULL; causes a forward declaration error!?
- options=NULL;
- // open codec
- //if (
- avcodec_open2(codecCtx, codec,&options);
- // < 0) ofLog(OF_LOG_ERROR, "ofxMovieExproter: Could not open codec");
-
- //do all the same for audio?
- audioStream = av_new_stream(formatCtx, 1); //???
- acodecCtx = audioStream->codec;
- acodecCtx->sample_rate=44100;
- acodecCtx->sample_fmt=AV_SAMPLE_FMT_S16;
- acodecCtx->channels=2;
- acodecCtx->channel_layout=AV_CH_LAYOUT_STEREO;
- avcodec_open2(acodecCtx, acodec,&options);
-
- if (outputFormat->flags & AVFMT_GLOBALHEADER) {
- videoStream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
- audioStream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
- }
-
-
- av_dump_format(formatCtx, 0, oss.str().c_str(), 1);
- }
-