Skip to content
Browse files

added setKeyFrameInterval method to control keyframe interval

  • Loading branch information...
1 parent ac80443 commit e7d482f3c50b13580fb263b4c65177ddb1a37a08 @pkrumins committed Jul 7, 2010
Showing with 78 additions and 4 deletions.
  1. +7 −2 readme.txt
  2. +71 −2 video.cc
View
9 readme.txt
@@ -46,6 +46,11 @@ to change it do this:
video.setFrameRate(50); // frame rate is now 50 fps
+The keyframe interval can also be controlled. Use `setKeyFrameInterval` to set it.
+It must be a power of two:
+
+ video.setKeyFrameInterval(128); // keyframe every 128 frames
+
Important: All of the above options should be set before submitting the first
frame.
@@ -88,8 +93,8 @@ Then set the output file:
stackedVideo.setOutputFile('./screencast.ogv');
-Then set the quality and/or framerate via `setQuality` and `setFrameRate`
-methods.
+Then set the quality, framerate, keyframe interval, via `setQuality`,
+`setFrameRate`, `setKeyFrameInterval` methods.
Now you have to submit a full frame to StackedVideo, do it via regular
`newFrame` method:
View
73 video.cc
@@ -7,6 +7,7 @@
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
+#include <cmath>
#include <theora/theoraenc.h>
using namespace v8;
@@ -71,7 +72,7 @@ rgb_to_yuv(const unsigned char *rgb, size_t size)
class VideoEncoder {
private:
- int width, height, quality, frameRate;
+ int width, height, quality, frameRate, keyFrameInterval;
std::string outputFileName;
FILE *ogg_fp;
@@ -87,6 +88,7 @@ class VideoEncoder {
public:
VideoEncoder(int wwidth, int hheight) :
width(wwidth), height(hheight), quality(31), frameRate(25),
+ keyFrameInterval(64),
hadFrame(false), ogg_fp(NULL), td(NULL), ogg_os(NULL) {}
~VideoEncoder() { end(); }
@@ -134,6 +136,10 @@ class VideoEncoder {
frameRate = fframeRate;
}
+ void setKeyFrameInterval(int kkeyFrameInterval) {
+ keyFrameInterval = kkeyFrameInterval;
+ }
+
void end() {
if (ogg_fp) {
fclose(ogg_fp);
@@ -170,7 +176,7 @@ class VideoEncoder {
ti.pixel_fmt = TH_PF_420;
ti.target_bitrate = 0;
ti.quality = quality;
- ti.keyframe_granule_shift=6; // keyframe every 64 frames
+ ti.keyframe_granule_shift = (int)log2(keyFrameInterval);
td = th_encode_alloc(&ti);
th_info_clear(&ti);
@@ -369,6 +375,7 @@ class FixedVideo : public ObjectWrap {
NODE_SET_PROTOTYPE_METHOD(t, "setOutputFile", SetOutputFile);
NODE_SET_PROTOTYPE_METHOD(t, "setQuality", SetQuality);
NODE_SET_PROTOTYPE_METHOD(t, "setFrameRate", SetFrameRate);
+ NODE_SET_PROTOTYPE_METHOD(t, "setKeyFrameInterval", SetKeyFrameInterval);
NODE_SET_PROTOTYPE_METHOD(t, "end", End);
target->Set(String::NewSymbol("FixedVideo"), t->GetFunction());
}
@@ -389,6 +396,10 @@ class FixedVideo : public ObjectWrap {
videoEncoder.setFrameRate(frameRate);
}
+ void SetKeyFrameInterval(int keyFrameInterval) {
+ videoEncoder.setKeyFrameInterval(keyFrameInterval);
+ }
+
void End() {
videoEncoder.end();
}
@@ -488,6 +499,9 @@ class FixedVideo : public ObjectWrap {
return VException("Frame rate must be integer.");
int rate = args[0]->Int32Value();
+
+ if (rate < 0)
+ return VException("Frame rate must be positive.");
FixedVideo *fv = ObjectWrap::Unwrap<FixedVideo>(args.This());
fv->SetFrameRate(rate);
@@ -496,6 +510,31 @@ class FixedVideo : public ObjectWrap {
}
static Handle<Value>
+ SetKeyFrameInterval(const Arguments &args)
+ {
+ HandleScope scope;
+
+ if (args.Length() != 1)
+ return VException("One argument required - keyframe interval.");
+
+ if (!args[0]->IsInt32())
+ return VException("Keyframe interval must be integer.");
+
+ int interval = args[0]->Int32Value();
+
+ if (interval < 0)
+ return VException("Keyframe interval must be positive.");
+
+ if ((interval & (interval - 1)) != 0)
+ return VException("Keyframe interval must be a power of two.");
+
+ FixedVideo *fv = ObjectWrap::Unwrap<FixedVideo>(args.This());
+ fv->SetKeyFrameInterval(interval);
+
+ return Undefined();
+ }
+
+ static Handle<Value>
End(const Arguments &args)
{
HandleScope scope;
@@ -536,6 +575,7 @@ class StackedVideo : public ObjectWrap {
NODE_SET_PROTOTYPE_METHOD(t, "setOutputFile", SetOutputFile);
NODE_SET_PROTOTYPE_METHOD(t, "setQuality", SetQuality);
NODE_SET_PROTOTYPE_METHOD(t, "setFrameRate", SetFrameRate);
+ NODE_SET_PROTOTYPE_METHOD(t, "setKeyFrameInterval", SetKeyFrameInterval);
NODE_SET_PROTOTYPE_METHOD(t, "end", End);
target->Set(String::NewSymbol("StackedVideo"), t->GetFunction());
}
@@ -609,6 +649,10 @@ class StackedVideo : public ObjectWrap {
videoEncoder.setFrameRate(frameRate);
}
+ void SetKeyFrameInterval(int keyFrameInterval) {
+ videoEncoder.setKeyFrameInterval(keyFrameInterval);
+ }
+
void End() {
videoEncoder.end();
}
@@ -774,6 +818,31 @@ class StackedVideo : public ObjectWrap {
}
static Handle<Value>
+ SetKeyFrameInterval(const Arguments &args)
+ {
+ HandleScope scope;
+
+ if (args.Length() != 1)
+ return VException("One argument required - keyframe interval.");
+
+ if (!args[0]->IsInt32())
+ return VException("Keyframe interval must be integer.");
+
+ int interval = args[0]->Int32Value();
+
+ if (interval < 0)
+ return VException("Keyframe interval must be positive.");
+
+ if ((interval & (interval - 1)) != 0)
+ return VException("Keyframe interval must be a power of two.");
+
+ StackedVideo *sv = ObjectWrap::Unwrap<StackedVideo>(args.This());
+ sv->SetKeyFrameInterval(interval);
+
+ return Undefined();
+ }
+
+ static Handle<Value>
End(const Arguments &args)
{
HandleScope scope;

0 comments on commit e7d482f

Please sign in to comment.
Something went wrong with that request. Please try again.