summaryrefslogtreecommitdiff
path: root/rotord
diff options
context:
space:
mode:
authorTim Redfern <tim@herge.(none)>2013-04-15 15:21:27 +0100
committerTim Redfern <tim@herge.(none)>2013-04-15 15:21:27 +0100
commit369836645c4d27f805b353439b8a109beaeeb736 (patch)
tree9bb005e4f535882f35711c8a53e4a7bfe1635996 /rotord
parent25b336a2b34d7a9bcf9e52a16ae962a1e261ae13 (diff)
made testcard
Diffstat (limited to 'rotord')
-rw-r--r--rotord/03.xml8
-rw-r--r--rotord/Makefile2
-rw-r--r--rotord/ofxMovieExporter.cpp302
-rw-r--r--rotord/ofxMovieExporter.h35
-rwxr-xr-xrotord/rotor.cpp94
-rwxr-xr-xrotord/rotor.h97
6 files changed, 256 insertions, 282 deletions
diff --git a/rotord/03.xml b/rotord/03.xml
new file mode 100644
index 0000000..f723ee7
--- /dev/null
+++ b/rotord/03.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<patchbay ID="0f7aa258-7c2f-11e2-abbd-133252267708">testcard ©Rotor 2013
+ <node ID="01" type="testcard" >testcard
+ </node>
+ <node ID="02" type="video_output">renders the video
+ <image_input from="01">video to output</image_input>
+ </node>
+</patchbay>
diff --git a/rotord/Makefile b/rotord/Makefile
index 6a7f48b..54f5b92 100644
--- a/rotord/Makefile
+++ b/rotord/Makefile
@@ -4,7 +4,7 @@ MY_CFLAGS = -fpermissive -std=c++11 -Wno-error
# -I ../ffmpeg
# The linker options.
-MY_LIBS = -lPocoNet -lPocoXML -lPocoUtil -lPocoFoundation -lvamp-hostsdk -lsndfile -L /usr/local/lib -lavcodec -lavformat -lavfilter -lavdevice -lavutil
+MY_LIBS = -lPocoNet -lPocoXML -lPocoUtil -lPocoFoundation -lvamp-hostsdk -lsndfile -L /usr/local/lib -lswscale -lavcodec -lavformat -lavfilter -lavdevice -lavutil
#MY_LIBS = ../libavcodec/ffmpeg/libavcodec/libavcodec.a ../libavcodec/ffmpeg/libavutil/libavutil.a ../libavcodec/ffmpeg/libavformat/libavformat.a ../libavcodec/ffmpeg/libavfilter/libavfilter.a ../libavcodec/ffmpeg/libavdevice/libavdevice.a -lPocoNet -lPocoXML -lPocoUtil -lPocoFoundation -lvamp-hostsdk
#GAH! HARD!
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");
}
-}
+
diff --git a/rotord/ofxMovieExporter.h b/rotord/ofxMovieExporter.h
index ae6b306..82c574c 100644
--- a/rotord/ofxMovieExporter.h
+++ b/rotord/ofxMovieExporter.h
@@ -91,10 +91,7 @@ extern "C"
//#include <libavutil/samplefmt.h>
//#include <libavutil/timestamp.h>
}
-
-namespace itg
-{
- class ofxMovieExporter
+class ofxMovieExporter
//#ifdef _THREAD_CAPTURE
// : public ofThread
//#endif
@@ -116,31 +113,16 @@ namespace itg
// tested so far with...
// codecId = CODEC_ID_MPEG4, container = "mp4"
// codecId = CODEC_ID_MPEG2VIDEO, container = "mov"
- void setup(int outW = OUT_W, int outH = OUT_H, int bitRate = BIT_RATE, int frameRate = FRAME_RATE, AVCodecID codecId = CODEC_ID, std::string container = CONTAINER);
- void record(std::string filePrefix=FILENAME_PREFIX, std::string folderPath="");
+ bool setup(int outW = OUT_W, int outH = OUT_H, int bitRate = BIT_RATE, int frameRate = FRAME_RATE, AVCodecID codecId = CODEC_ID, std::string container = CONTAINER);
+ bool record(std::string filePrefix=FILENAME_PREFIX, std::string folderPath="");
+ void finishRecord();
void stop();
bool isRecording() const;
- // set the recording area
- // x, y is the upper left corner of the recording area, default: 0, 0
- // w x h is the area size, default: viewport width x height
- void setRecordingArea(int x, int y, int w, int h);
- void setRecordingArea(int rect);
-
- // reset the recording area to the size of the current viewport (screen, FBO, etc)
- void resetRecordingArea();
-
- // get the recording area as a rectangle
- int getRecordingArea();
-
// set an external pixel source, assumes 3 Byte RGB
// also sets the recording size but does not crop to the recording area
void setPixelSource(unsigned char* pixels, int w, int h);
- // reset the pixel source and record from the screen
- // also resets the recording size to the viewport width
- void resetPixelSource();
-
// get the number files that have been captured so far
int getNumCaptures();
@@ -151,6 +133,8 @@ namespace itg
inline int getRecordingWidth() {return outW;}
inline int getRecordingHeight() {return outH;}
+ void encodeFrame(char *pixels);
+
private:
//#ifdef _THREAD_CAPTURE
// void threadedFunction();
@@ -163,9 +147,8 @@ namespace itg
void allocateMemory();
void clearMemory();
- void checkFrame();//ofEventArgs& args);
void encodeFrame();
- void finishRecord();
+
std::string container;
AVCodecID codecId;
@@ -203,7 +186,3 @@ namespace itg
unsigned char* pixelSource;
};
- inline bool ofxMovieExporter::isRecording() const { return recording; }
-}
-
-namespace Apex = itg;
diff --git a/rotord/rotor.cpp b/rotord/rotor.cpp
index ee170f0..cffb929 100755
--- a/rotord/rotor.cpp
+++ b/rotord/rotor.cpp
@@ -486,6 +486,19 @@ bool Graph::load(string &filename){
}
else cerr << "Rotor: linking input " << i2 << " of node: '" << nodeID << "', cannot find target '" << fromID << "'" << endl;
}
+ int n3=xml.getNumTags("image_input");
+ for (int i3=0;i3<n3;i3++){
+ nodes[nodeID]->create_image_input(xml.getValue("image_input","",i3));
+ string fromID=xml.getAttribute("image_input","from","",i2);
+ if (nodes.find(fromID)!=nodes.end()) {
+ if (!nodes[nodeID]->inputs[i3]->connect((Image_node*)nodes[fromID])){
+ cerr << "Rotor: graph loader cannot connect input " << i3 << " of node '" << nodeID << "' to node '" << fromID << "'" << endl;
+ return false;
+ }
+ else cerr << "Rotor: linked input " << i3 << " of node '" << nodeID << "' to node '" << fromID << "'" << endl;
+ }
+ else cerr << "Rotor: linking input " << i3 << " of node: '" << nodeID << "', cannot find target '" << fromID << "'" << endl;
+ }
xml.popTag();
}
}
@@ -507,6 +520,7 @@ Node_factory::Node_factory(){
add_type("divide",new Signal_divide());
add_type("bang",new Is_new_integer());
add_type("signal_output",new Signal_output());
+ add_type("testcard",new Testcard());
add_type("video_output",new Video_output());
}
bool Audio_thumbnailer::init(int _channels,int _bits,int _samples,int _rate) {
@@ -742,18 +756,47 @@ bool Video_output::render(const float duration, const float framerate,const stri
*/
bool Video_output::render(const float duration, const float framerate,const string &output_filename,const string &audio_filename){
+ //
+ //setup defaults
+ int outW=640;
+ int outH=480;
+ int bitRate=4000000;
+ int frameRate=25;
+ AVCodecID codecId=AV_CODEC_ID_H264;
+ std::string container ="mov";
+
+
+ if (exporter->setup(outW,outH,bitRate,frameRate,codecId,container)) {
+ if (exporter->record(output_filename)) {
+
+ cerr << "Rotor: Video_output rendering " << duration << " seconds at " << framerate << " fps" << endl;
+ float step=1.0f/framerate;
+ float v=0.0f;
+ for (float f=0.0f;f<duration;f+=step) {
+ exporter->encodeFrame(get_output(Frame_spec(f,framerate,outW,outH))->RGBdata);
+ }
+ exporter->finishRecord();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//new version from libav examples
+/*
AVOutputFormat *fmt;
AVFormatContext *oc;
AVStream *audio_st, *video_st;
double audio_pts, video_pts;
int i;
- /* Initialize libavcodec, and register all codecs and formats. */
+ //Initialize libavcodec, and register all codecs and formats. //
av_register_all();
//think about this: when to register and unregister?
- /* Autodetect the output format from the name. default is MPEG. */
+ //Autodetect the output format from the name. default is MPEG. //
fmt = av_guess_format(NULL, output_filename.c_str(), NULL);
if (!fmt) {
printf("Could not deduce output format from file extension: using MPEG.\n");
@@ -764,7 +807,7 @@ bool Video_output::render(const float duration, const float framerate,const stri
return false;
}
- /* Allocate the output media context. */
+ //Allocate the output media context. //
oc = avformat_alloc_context();
if (!oc) {
cerr <<"Rotor: memory error"<< endl;
@@ -773,8 +816,8 @@ bool Video_output::render(const float duration, const float framerate,const stri
oc->oformat = fmt;
snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
- /* Add the audio and video streams using the default format codecs
- * and initialize the codecs. */
+ //Add the audio and video streams using the default format codecs
+ * and initialize the codecs. //
video_st = NULL;
audio_st = NULL;
if (fmt->video_codec != AV_CODEC_ID_NONE) {
@@ -784,8 +827,8 @@ bool Video_output::render(const float duration, const float framerate,const stri
audio_st = add_audio_stream(oc, fmt->audio_codec);
}
- /* Now that all the parameters are set, we can open the audio and
- * video codecs and allocate the necessary encode buffers. */
+ //Now that all the parameters are set, we can open the audio and
+ * video codecs and allocate the necessary encode buffers. //
if (video_st)
open_video(oc, video_st);
if (audio_st)
@@ -793,19 +836,19 @@ bool Video_output::render(const float duration, const float framerate,const stri
av_dump_format(oc, 0, filename, 1);
- /* open the output file, if needed */
+ //open the output file, if needed //
if (!(fmt->flags & AVFMT_NOFILE)) {
if (avio_open(&oc->pb, filename, AVIO_FLAG_WRITE) < 0) {
- fprintf(stderr, "Could not open '%s'\n", filename);
- return 1;
+ cerr <<"Could not open "<<output_filename<<endl;
+ return false;
}
}
- /* Write the stream header, if any. */
+ //Write the stream header, if any. //
avformat_write_header(oc, NULL);
for (;;) {
- /* Compute current audio and video time. */
+ //Compute current audio and video time. //
if (audio_st)
audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
else
@@ -821,7 +864,7 @@ bool Video_output::render(const float duration, const float framerate,const stri
(!video_st || video_pts >= STREAM_DURATION))
break;
- /* write interleaved audio and video frames */
+ //write interleaved audio and video frames //
if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
write_audio_frame(oc, audio_st);
} else {
@@ -829,30 +872,33 @@ bool Video_output::render(const float duration, const float framerate,const stri
}
}
- /* Write the trailer, if any. The trailer must be written before you
- * close the CodecContexts open when you wrote the header; otherwise
- * av_write_trailer() may try to use memory that was freed on
- * av_codec_close(). */
- av_write_trailer(oc);
+ //Write the trailer, if any. The trailer must be written before you
+ // close the CodecContexts open when you wrote the header; otherwise
+ // av_write_trailer() may try to use memory that was freed on
+ // av_codec_close(). //
+ //av_write_trailer(oc);
- /* Close each codec. */
+ //Close each codec. //
if (video_st)
close_video(oc, video_st);
if (audio_st)
close_audio(oc, audio_st);
- /* Free the streams. */
+ //Free the streams. //
for (i = 0; i < oc->nb_streams; i++) {
av_freep(&oc->streams[i]->codec);
av_freep(&oc->streams[i]);
}
if (!(fmt->flags & AVFMT_NOFILE))
- /* Close the output file. */
+ //Close the output file. //
avio_close(oc->pb);
- /* free the stream */
+ //free the stream //
av_free(oc);
- return 0;
-} \ No newline at end of file
+ return true;
+ */
+
+
+
diff --git a/rotord/rotor.h b/rotord/rotor.h
index 9728909..4a6c8d3 100755
--- a/rotord/rotor.h
+++ b/rotord/rotor.h
@@ -153,6 +153,16 @@ namespace Rotor {
return Time_spec(seconds-(1.0f/framerate),framerate);
}
};
+ class Frame_spec{
+ public:
+ Frame_spec(float _time,float _framerate,int _w,int _h){ time=_time; framerate=_framerate; w=_w; h=_h;};
+ float time;
+ float framerate;
+ int h,w;
+ Frame_spec lastframe(){
+ return Frame_spec(time-(1.0f/framerate),framerate,w,h);
+ }
+ };
class Render_status{
public:
int id;
@@ -177,7 +187,8 @@ namespace Rotor {
};
class Image_input: public Input{
public:
-
+ bool connect(Image_node* source);
+ Image_input(const string &_desc): Input(_desc){};
};
class Signal_input: public Input{
public:
@@ -205,7 +216,46 @@ namespace Rotor {
}
};
class Image{
- char* data;
+ public:
+ Image(){
+ zero();
+ };
+ Image(int _w,int _h){
+ setup(_w,_h);
+ };
+ ~Image() {
+ free();
+ };
+ void free(){
+ if (RGBdata) delete[] RGBdata;
+ if (Adata) delete[] Adata;
+ if (Zdata) delete[] Zdata;
+ zero();
+ }
+ void zero(){
+ RGBdata=nullptr;
+ Adata=nullptr;
+ Zdata=nullptr;
+ w=0;
+ h=0;
+ }
+ bool setup(int _w,int _h){
+ if (w!=_w||h!=_h){
+ free();
+ w=_w;
+ h=_h;
+ RGBdata=new uint8_t[w*h*3];
+ Adata=new uint8_t[w*h];
+ Zdata=new uint16_t[w*h];
+ return true;
+ }
+ else return false;
+ }
+ uint8_t *RGBdata;
+ uint8_t *Adata;
+ uint16_t *Zdata;
+ private:
+ int h,w;
};
class Signal_node: public Node{
public:
@@ -214,13 +264,13 @@ namespace Rotor {
class Image_node: public Node{
public:
vector<Image_input> image_inputs; //image node also has image inputs and outputs
- Image* get_output(const Time_spec &time){ //sample implementation
+ Image *get_output(const Frame_spec &frame){ //sample implementation
//do something with the inputs
//and then
- return ((Image_node*)image_inputs[0].connection)->get_output(time);
+ return ((Image_node*)image_inputs[0].connection)->get_output(frame);
}
- void get_preview(const Time_spec &time);
- Image* image; //this can be privately allocated or just passed on as the node see fit
+ Image *get_preview(const Frame_spec &frame);
+ Image *image; //this can be privately allocated or just passed on as the node see fit
private:
float image_time;
};
@@ -315,14 +365,45 @@ namespace Rotor {
else return 0.0f;
}
};
+ class Testcard: public Image_node {
+ public:
+ Testcard(){};
+ Testcard(map<string,string> &settings) {
+ base_settings(settings);
+ };
+ Testcard* clone(map<string,string> &_settings) { return new Testcard(_settings);};
+ Image *get_output(const Frame_spec &frame){
+ if (image->setup(frame.w,frame.h)) {
+ //create testcard
+ float ws=(255.0f/frame.w);
+ float hs=(255.0f/frame.h);
+ for (int i=0;i<frame.h;i++){
+ for (int j=0;j<frame.w;j++){
+ image->RGBdata[i*frame.w+j]=(uint8_t)(i*hs);
+ image->RGBdata[i*frame.w+j+1]=(uint8_t)(j*ws);
+ image->RGBdata[i*frame.w+j+2]=(uint8_t)(0);
+ image->Adata[i*frame.w+j]=(uint8_t)255;
+ image->Zdata[i*frame.w+j]=(uint16_t)512; //1.0 in fixed point 8.8 bits
+ }
+ }
+ }
+ return image;
+ }
+ private:
+ Image *image;
+ };
class Video_output: public Image_node {
public:
Video_output(){};
Video_output(map<string,string> &settings) {
base_settings(settings);
+ exporter=new ofxMovieExporter();
};
Video_output* clone(map<string,string> &_settings) { return new Video_output(_settings);};
- bool render(const float duration, const float framerate,const string &output_filename,const string &audio_filename);
+ bool render(const float duration, const float framerate,const string &output_filename,const string &audio_filename);
+
+ private:
+ ofxMovieExporter *exporter;
};
//-------------------------------------------------------------------
class Node_factory{
@@ -448,6 +529,6 @@ namespace Rotor {
/*
coding style
-Types begin with capitals 'CamelCase'
+Types begin with capitals 'New_type'
variables/ instances use lower case with underscore as a seperator
*/