[Sumover-dev] [svn commit] r4656 - vic/branches/mpeg4/video

sumover-dev at cs.ucl.ac.uk sumover-dev at cs.ucl.ac.uk
Mon Mar 1 13:12:28 GMT 2010


Author: douglask
Date: Mon Mar  1 13:12:28 2010
New Revision: 4656

Modified:
   vic/branches/mpeg4/video/grabber-decklink.cpp

Log:
Initial ffmpeg's swcale support for decklink grabber

Modified: vic/branches/mpeg4/video/grabber-decklink.cpp
==============================================================================
--- vic/branches/mpeg4/video/grabber-decklink.cpp	(original)
+++ vic/branches/mpeg4/video/grabber-decklink.cpp	Mon Mar  1 13:12:28 2010
@@ -54,7 +54,14 @@
 #include "DeckLinkAPIDispatch.cpp"
 #endif
 
+#ifdef HAVE_SWSCALE
+extern "C" {
+#include "libswscale/swscale.h"
+#include "libavutil/avutil.h"
+}
+#else
 #include "yuv_convert.h"
+#endif
 
 #if !defined(_WIN32) && !defined(_WIN64)
 #undef debug_msg
@@ -78,13 +85,19 @@
 
 class DeckLinkCaptureDelegate : public IDeckLinkInputCallback {
 public:
-    DeckLinkCaptureDelegate(int32_t width, int32_t height) {
+    DeckLinkCaptureDelegate(int32_t width, int32_t height, int format) {
         mRefCount = 1;
         mReadIndex = 0;
         mWriteIndex = 0;
+#ifdef HAVE_SWSCALE
+        sws_context = NULL;
+#endif
+        outw = width;
+        outh = height;
+        cformat = format;
         for (int i = 0; i < mBufferSize; i++) {
             mBuffer[i] = new uint8_t[width * height * 2];
-            memset((void *)mBuffer[i], width * height, sizeof(uint8_t));
+            memset((void *)mBuffer[i], width * height * 2, sizeof(uint8_t));
         }
     }
 
@@ -148,6 +161,11 @@
         newRefValue = __sync_fetch_and_sub(&mRefCount, 1);
 #endif
         if (newRefValue == 0) {
+#ifdef HAVE_SWSCALE
+            if (sws_context != NULL){
+                sws_freeContext(sws_context);
+            }
+#endif
             delete this;
             return 0;
         }
@@ -160,9 +178,61 @@
         arrivedFrame->GetBytes(&videoFrame);
 
         int nextElementIndex = (mWriteIndex + 1) % mBufferSize;
-        
+
         if(nextElementIndex != mReadIndex) {
+#ifdef HAVE_SWSCALE
+            int flags = SWS_FAST_BILINEAR;
+
+            if (sws_context == NULL){
+
+#ifdef RUNTIME_CPUDETECT
+                flags |= (available_cpu_flags & FF_CPU_MMX ? SWS_CPU_CAPS_MMX : 0);
+                flags |= (available_cpu_flags & FF_CPU_MMXEXT ? SWS_CPU_CAPS_MMX2 : 0);
+                flags |= (available_cpu_flags & FF_CPU_3DNOW ? SWS_CPU_CAPS_3DNOW : 0);
+                flags |= (available_cpu_flags & FF_CPU_ALTIVEC ? SWS_CPU_CAPS_ALTIVEC : 0);
+#elif defined(HAVE_MMX)
+                flags |= SWS_CPU_CAPS_MMX;
+#if defined(HAVE_MMX2)
+                flags |= SWS_CPU_CAPS_MMX2;
+#endif
+#elif defined(HAVE_3DNOW)
+                flags |= SWS_CPU_CAPS_3DNOW;
+#endif
+                PixelFormat in_format = PIX_FMT_UYVY422;
+
+                PixelFormat out_format = PIX_FMT_YUV420P;
+                if (cformat == CF_422) {
+                    out_format = PIX_FMT_YUV422P;
+                }
+
+                // Accelerated Colour conversion routines
+                sws_context = sws_getContext(arrivedFrame->GetWidth(), arrivedFrame->GetHeight(), in_format,
+                                             outw, outh, out_format, flags, NULL, NULL, NULL);
+                if(sws_context == NULL){
+                    debug_msg("DeckLinkCaptureDelegate: error! cannot allocate memory for swscontext!\n");
+                    return S_FALSE;
+                } 
+            }
+
+            sws_src[0] = (uint8_t*)videoFrame;
+            sws_src[1] = sws_src[2] = NULL;
+            sws_src_stride[0] = arrivedFrame->GetRowBytes();
+            sws_src_stride[1] = sws_src_stride[2] = 0;
+
+            sws_tar[0] = (uint8_t*)mBuffer[mWriteIndex];
+            sws_tar[1] = sws_tar[0] + outw * outh;
+            if (cformat == CF_422) {
+                sws_tar[2] = sws_tar[1] + outw * outh / 2;
+            } else {
+                sws_tar[2] = sws_tar[1] + outw * outh / 4;
+            }
+            sws_tar_stride[0] = outw;
+            sws_tar_stride[1] = sws_tar_stride[2] = outw/2;
+
+            sws_scale(sws_context, sws_src, sws_src_stride, 0, arrivedFrame->GetHeight(), sws_tar, sws_tar_stride);
+#else
             memcpy((void *)(mBuffer[mWriteIndex]), videoFrame, arrivedFrame->GetRowBytes() * arrivedFrame->GetHeight());
+#endif
 
 // fprintf(stderr, "*push* mBuffer[%i] = 0x%lx\n", mWriteIndex, mBuffer[mWriteIndex]);
             mWriteIndex = nextElementIndex;
@@ -176,13 +246,20 @@
         return S_OK;
     }
 
-
 private:
     volatile int32_t mRefCount;
     volatile int32_t mReadIndex;
     volatile int32_t mWriteIndex;
     static const int32_t mBufferSize = 4;
     volatile uint8_t *mBuffer[mBufferSize];
+#ifdef HAVE_SWSCALE
+    SwsContext *sws_context;
+    uint8_t *sws_src[3];
+    uint8_t *sws_tar[3];
+    int sws_src_stride[3];
+    int sws_tar_stride[3];
+#endif
+    int cformat, outw, outh;
 };
 
 
@@ -207,8 +284,6 @@
     BMDDisplayMode displayMode_;
     long displayModeWidth_;
     long displayModeHeight_;
-    BMDTimeValue displayModeFrameDuration_;
-    BMDTimeScale displayModeTimeScale_;
 
     DeckLinkCaptureDelegate *delegate_;
 };
@@ -342,8 +417,8 @@
         return;
     }
 
-    strcpy(attr,"format { 420 422 } ");
-    strcat(attr,"size { large } ");
+    strcpy(attr,"format { 420 422 cif } ");
+    strcat(attr,"size { small cif large } ");
 
     strcat(attr,"port { ");
 
@@ -455,6 +530,8 @@
                 tcl.result(o->name());
             return (TCL_OK);
         }
+    } else if (argc == 2) {
+        tcl.evalc("set_software_scale_buttons_state");
     }
     return (InputDevice::command(argc, argv));
 }
@@ -478,6 +555,7 @@
         debug_msg("DecLinkDevice: Could not obtain the IDeckLinkInput interface\n");
     }
     running_  = 0;
+    delegate_ = NULL;
 }
 
 int DeckLinkGrabber::command(int argc, const char*const* argv)
@@ -485,16 +563,20 @@
     HRESULT result;
 
     if (argc == 3) {
-        if (strcmp(argv[1], "decimate") == 0) {
+        if (strcmp(argv[1], "setSoftwareScale") == 0) {
+            if (running_) {
+                stop(); start();
+            }
+            return (TCL_OK);
+
+        } else if (strcmp(argv[1], "decimate") == 0) {
             decimate_ = atoi(argv[2]);
 
             if (running_) {
                 stop(); start();
             }
             return (TCL_OK);
-        }
-
-        if (strcmp(argv[1], "port") == 0) {
+        } else if (strcmp(argv[1], "port") == 0) {
             IDeckLinkConfiguration *deckLinkConfiguration = NULL;
             BMDVideoConnection bmdVideoConnection = bmdVideoConnectionHDMI;
 
@@ -540,13 +622,11 @@
             }
         
             return (TCL_OK);
-        }
 
-        if (strcmp(argv[1], "fps") == 0) {
+        } else if (strcmp(argv[1], "fps") == 0) {
             debug_msg("DecLinkGrabber: fps %s\n",argv[2]);
-        }
 
-        if (strcmp(argv[1], "type") == 0 || strcmp(argv[1], "format") == 0) {
+        } else if (strcmp(argv[1], "type") == 0 || strcmp(argv[1], "format") == 0) {
 
             IDeckLinkDisplayModeIterator *displayModeIterator = NULL;
             IDeckLinkDisplayMode *displayMode = NULL;
@@ -594,8 +674,6 @@
                         displayMode_ = displayMode->GetDisplayMode();
                         displayModeWidth_ = displayMode->GetWidth();
                         displayModeHeight_ = displayMode->GetHeight();
-                        displayMode->GetFrameRate(&displayModeFrameDuration_, &displayModeTimeScale_);
-fprintf(stderr, "DisplayMode width=%li height=%li frame duration=%li time scale=%li\n", displayModeWidth_, displayModeHeight_,displayModeFrameDuration_,  displayModeTimeScale_);
                         break;
                     }
                 }
@@ -632,17 +710,37 @@
     if (deckLinkInput_ != NULL) {
         deckLinkInput_->Release();
     }
+    if (delegate_ != NULL) {
+        delegate_->Release();
+    }
 }
 
 void DeckLinkGrabber::start()
 {
     HRESULT result;
+    int flags = TCL_GLOBAL_ONLY;
+    Tcl& tcl = Tcl::instance();
+    const char* setSoftwareScale = Tcl_GetVar(tcl.interp(), "setSoftwareScale", flags);
 
     // Set the image size.
     switch (decimate_) {
     case 1: // full-sized
-        width_ = displayModeWidth_;
-        height_ = displayModeHeight_;
+        if (strcmp(setSoftwareScale, "960p") == 0) {
+            width_ = int(960 * displayModeWidth_ / displayModeHeight_);
+            height_ = 960;
+        } else if (strcmp(setSoftwareScale, "720p") == 0) {
+            width_ = int(720 * displayModeWidth_ / displayModeHeight_);
+            height_ = 720;
+        } else if (strcmp(setSoftwareScale, "576p") == 0) {
+          width_ = int(576 * displayModeWidth_ / displayModeHeight_);
+          height_ = 576;
+        } else if (strcmp(setSoftwareScale, "480p") == 0) {
+          width_ = int(480 * displayModeWidth_ / displayModeHeight_);
+          height_ = 480;
+        } else {
+          width_ = displayModeWidth_;
+          height_ = displayModeHeight_;
+        }
         break;
     case 2: // CIF-sized
         width_ = CIF_WIDTH;
@@ -672,7 +770,10 @@
         return;
     }
 
-    delegate_ = new DeckLinkCaptureDelegate(width_, height_);
+    if (delegate_) {
+        delegate_->Release();
+    }
+    delegate_ = new DeckLinkCaptureDelegate(outw_, outh_, cformat_);
 
     result = deckLinkInput_->SetCallback(delegate_);
 
@@ -713,11 +814,27 @@
         return 0;
     }
 
+    if (!running_) {
+        return 0;
+    }
+
     uint8_t *fr = delegate_->GetVideoFrame();
     if (fr == NULL) {
         return 0;
     }
 
+#ifdef HAVE_SWSCALE
+    switch (cformat_) {
+    case CF_420:
+    case CF_CIF:
+        memcpy((char *)frame_, (char *)fr, outw_ * outh_ * 3 / 2);
+      break;
+
+    case CF_422:
+        memcpy((char *)frame_, (char *)fr, outw_ * outh_ * 2);
+      break;
+    }
+#else
     switch (cformat_) {
     case CF_420:
     case CF_CIF:
@@ -728,7 +845,7 @@
         packedUYVY422_to_planarYUYV422((char *)frame_, outw_, outh_, (char *)fr, inw_, inh_);
       break;
     }
-
+#endif
     suppress(frame_);
     saveblks(frame_);
     YuvFrame f(media_ts(), frame_, crvec_, outw_, outh_);



More information about the Sumover-dev mailing list