Permalink
Browse files

Added NAVThumbnail module to efficiently generate jpeg thumbnails.

  • Loading branch information...
1 parent 9b9f2a6 commit 6b6c096f3571bd33527a767ec0ba5fb5be9dd2d5 @manast manast committed Feb 23, 2012
Showing with 230 additions and 3 deletions.
  1. +1 −0 src/navcodec.cpp
  2. +1 −1 src/navcodec.h
  3. +169 −0 src/navthumbnail.cpp
  4. +58 −0 src/navthumbnail.h
  5. +1 −2 wscript
View
@@ -54,6 +54,7 @@ extern "C" { // Cause of name mangling in C++, we use extern C here
NAVOutputFormat::Init(target);
NAVSws::Init(target);
NAVResample::Init(target);
+ NAVThumbnail::Init(target);
target->Set(String::NewSymbol("relocateMoov"), FunctionTemplate::New(RelocateMoov)->GetFunction());
View
@@ -29,5 +29,5 @@
#include "navsws.h"
#include "navresample.h"
#include "navdictionary.h"
+#include "navthumbnail.h"
#include "relocatemoov.h"
-
View
@@ -0,0 +1,169 @@
+/* Copyright(c) 2012 Optimal Bits Sweden AB. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "navthumbnail.h"
+
+#include "navformat.h"
+#include "navframe.h"
+#include "navutils.h"
+
+using namespace v8;
+
+
+#define MAX_BPP 4
+
+NAVThumbnail::NAVThumbnail(){
+ pContext = NULL;
+ pBuffer = NULL;
+}
+
+NAVThumbnail::~NAVThumbnail(){
+ printf("NAVThumbnail destructor\n");
+ av_free(pBuffer);
+ if(pContext){
+ avcodec_close(pContext);
+ av_free(pContext);
+ }
+}
+
+Persistent<FunctionTemplate> NAVThumbnail::templ;
+
+void NAVThumbnail::Init(Handle<Object> target){
+ HandleScope scope;
+
+ // Our constructor
+ Local<FunctionTemplate> templ = FunctionTemplate::New(New);
+
+ NAVThumbnail::templ = Persistent<FunctionTemplate>::New(templ);
+
+ NAVThumbnail::templ->InstanceTemplate()->SetInternalFieldCount(1); // 1 since this is a constructor function
+ NAVThumbnail::templ->SetClassName(String::NewSymbol("NAVThumbnail"));
+
+ NODE_SET_PROTOTYPE_METHOD(NAVThumbnail::templ, "write", Write);
+
+ target->Set(String::NewSymbol("NAVThumbnail"), NAVThumbnail::templ->GetFunction());
+}
+
+// (options)
+Handle<Value> NAVThumbnail::New(const Arguments& args) {
+ HandleScope scope;
+
+ NAVThumbnail* instance = new NAVThumbnail();
+
+ instance->Wrap(args.This());
+
+ if(args.Length()<1){
+ return ThrowException(Exception::TypeError(String::New("Missing input parameter (srcStream)")));
+ }
+
+ Local<Object> options = Local<Object>::Cast(args[0]);
+
+ AVCodec *pCodec = avcodec_find_encoder(CODEC_ID_MJPEG);
+ if (!pCodec) {
+ return ThrowException(Exception::TypeError(String::New("Could not alloc codec")));
+ }
+
+ instance->pContext = avcodec_alloc_context3(pCodec);
+ if (!instance->pContext) {
+ return ThrowException(Exception::TypeError(String::New("Could not alloc codec context")));
+ }
+
+ instance->pContext->width = GET_OPTION_UINT32(options, width, 128);
+ instance->pContext->height = GET_OPTION_UINT32(options, height, 128);;
+ instance->pContext->pix_fmt = (PixelFormat) GET_OPTION_UINT32(options, pix_fmt, PIX_FMT_YUVJ420P);
+
+ instance->pContext->time_base.num = 1;
+ instance->pContext->time_base.den = 1;
+
+ AVDictionary *pDict = NAVDictionary::New(options);
+ if (avcodec_open2(instance->pContext, pCodec, &pDict) < 0) {
+ av_dict_free(&pDict);
+ delete instance;
+ return ThrowException(Exception::TypeError(String::New("Could not open codec")));
+ }
+ av_dict_free(&pDict);
+
+ instance->bufferSize = (instance->pContext->width * instance->pContext->height * MAX_BPP) / 8;
+ instance->bufferSize = instance->bufferSize < FF_MIN_BUFFER_SIZE ?
+ FF_MIN_BUFFER_SIZE:instance->bufferSize;
+
+ instance->pBuffer = (uint8_t *) av_mallocz(instance->bufferSize);
+ if (instance->pBuffer == NULL){
+ return ThrowException(Exception::Error(String::New("Error allocating buffer")));
+ }
+
+ return args.This();
+}
+
+// (frame, filename, cb(err))
+Handle<Value> NAVThumbnail::Write(const Arguments& args) {
+ HandleScope scope;
+ Local<Object> frame;
+ Local<Function> callback;
+
+ if(args.Length()<3){
+ return ThrowException(Exception::TypeError(String::New("Missing input parameters (frame, filename, cb)")));
+ }
+ frame = Local<Array>::Cast(args[0]);
+
+ AVFrame *pFrame = (node::ObjectWrap::Unwrap<NAVFrame>(frame))->pContext;
+
+ String::Utf8Value v8str(args[1]);
+ char *filename = strdup(*v8str);
+ if(filename == NULL){
+ return ThrowException(Exception::Error(String::New("Error allocating filename string")));
+ }
+
+ if(!(args[2]->IsFunction())){
+ return ThrowException(Exception::TypeError(String::New("Third parameter must be a funcion")));
+ }
+
+ callback = Local<Function>::Cast(args[2]);
+
+ NAVThumbnail* instance = UNWRAP_OBJECT(NAVThumbnail, args);
+
+ pFrame->pts = 1;
+ pFrame->quality = instance->pContext->global_quality;
+ int encodedSize = avcodec_encode_video(instance->pContext, instance->pBuffer, instance->bufferSize, pFrame);
+ if(encodedSize<=0){
+ return ThrowException(Exception::Error(String::New("Error encoding file")));
+ }
+
+ FILE *fileHandle = fopen(filename, "wb");
+ if(fileHandle == NULL){
+ return ThrowException(Exception::Error(String::New("Error opening thumbnail file")));
+ }
+
+ int ret = fwrite(instance->pBuffer, 1, encodedSize, fileHandle);
+ fclose(fileHandle);
+
+ // TODO: Make asynchronous
+ if (ret < encodedSize) {
+ Local<Value> err = Exception::Error(String::New("Error writing thumbnail"));
+ Local<Value> argv[] = { err };
+ callback->Call(Context::GetCurrent()->Global(), 1, argv);
+ } else {
+ Local<Value> argv[] = { Local<Value>::New(Null()) };
+ callback->Call(Context::GetCurrent()->Global(), 1, argv);
+ }
+
+ return Undefined();
+}
+
View
@@ -0,0 +1,58 @@
+/* Copyright(c) 2012 Optimal Bits Sweden AB. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef _NAVTHUMBNAIL_H
+#define _NAVTHUMBNAIL_H
+
+#include "navcodec.h"
+
+#include <v8.h>
+#include <node.h>
+
+extern "C" {
+#include <libavcodec/avcodec.h>
+#include <libavformat/avformat.h>
+}
+
+using namespace v8;
+
+class NAVThumbnail : node::ObjectWrap {
+private:
+ AVCodecContext *pContext;
+ uint64_t bufferSize;
+ uint8_t *pBuffer;
+
+public:
+ NAVThumbnail();
+ ~NAVThumbnail();
+
+ static Persistent<FunctionTemplate> templ;
+
+ static void Init(Handle<Object> target);
+
+ // (srcStream, dstStream)
+ static Handle<Value> New(const Arguments& args);
+
+ // (srcFrame) -> dstFrame
+ static Handle<Value> Write(const Arguments& args);
+};
+
+#endif // _NAVTHUMBNAIL_H
+
View
@@ -14,6 +14,5 @@ def build(bld):
obj.cxxflags = ["-g", "-D__STDC_CONSTANT_MACROS", "-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE", "-Wall"]
obj.linkflags = ["-lavcodec","-lavformat","-lswscale","-lavutil"]
obj.target = "navcodec"
- obj.source = ["src/navcodec.cpp", "src/navcodeccontext.cpp", "src/navframe.cpp", "src/navformat.cpp", "src/navstream.cpp", "src/navoutformat.cpp","src/navpixformat.cpp", "src/navsws.cpp", "src/navcodecid.cpp", "src/navresample.cpp", "src/navaudiofifo.cpp", "src/navdictionary.cpp", "src/relocatemoov.cpp" ]
+ obj.source = ["src/navcodec.cpp", "src/navcodeccontext.cpp", "src/navframe.cpp", "src/navformat.cpp", "src/navstream.cpp", "src/navoutformat.cpp","src/navpixformat.cpp", "src/navsws.cpp", "src/navcodecid.cpp", "src/navresample.cpp", "src/navaudiofifo.cpp", "src/navdictionary.cpp", "src/navthumbnail.cpp", "src/relocatemoov.cpp"]
obj.uselib = ['libavcodec', 'libavformat', 'libswscale','-lavutil']
-

0 comments on commit 6b6c096

Please sign in to comment.