Changeset 4656

Show
Ignore:
Timestamp:
03/01/10 13:12:28 (4 years ago)
Author:
douglask
Message:

Initial ffmpeg's swcale support for decklink grabber

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • vic/branches/mpeg4/video/grabber-decklink.cpp

    r4632 r4656  
    5555#endif 
    5656 
     57#ifdef HAVE_SWSCALE 
     58extern "C" { 
     59#include "libswscale/swscale.h" 
     60#include "libavutil/avutil.h" 
     61} 
     62#else 
    5763#include "yuv_convert.h" 
     64#endif 
    5865 
    5966#if !defined(_WIN32) && !defined(_WIN64) 
     
    7986class DeckLinkCaptureDelegate : public IDeckLinkInputCallback { 
    8087public: 
    81     DeckLinkCaptureDelegate(int32_t width, int32_t height) { 
     88    DeckLinkCaptureDelegate(int32_t width, int32_t height, int format) { 
    8289        mRefCount = 1; 
    8390        mReadIndex = 0; 
    8491        mWriteIndex = 0; 
     92#ifdef HAVE_SWSCALE 
     93        sws_context = NULL; 
     94#endif 
     95        outw = width; 
     96        outh = height; 
     97        cformat = format; 
    8598        for (int i = 0; i < mBufferSize; i++) { 
    8699            mBuffer[i] = new uint8_t[width * height * 2]; 
    87             memset((void *)mBuffer[i], width * height, sizeof(uint8_t)); 
     100            memset((void *)mBuffer[i], width * height * 2, sizeof(uint8_t)); 
    88101        } 
    89102    } 
     
    149162#endif 
    150163        if (newRefValue == 0) { 
     164#ifdef HAVE_SWSCALE 
     165            if (sws_context != NULL){ 
     166                sws_freeContext(sws_context); 
     167            } 
     168#endif 
    151169            delete this; 
    152170            return 0; 
     
    161179 
    162180        int nextElementIndex = (mWriteIndex + 1) % mBufferSize; 
    163          
     181 
    164182        if(nextElementIndex != mReadIndex) { 
     183#ifdef HAVE_SWSCALE 
     184            int flags = SWS_FAST_BILINEAR; 
     185 
     186            if (sws_context == NULL){ 
     187 
     188#ifdef RUNTIME_CPUDETECT 
     189                flags |= (available_cpu_flags & FF_CPU_MMX ? SWS_CPU_CAPS_MMX : 0); 
     190                flags |= (available_cpu_flags & FF_CPU_MMXEXT ? SWS_CPU_CAPS_MMX2 : 0); 
     191                flags |= (available_cpu_flags & FF_CPU_3DNOW ? SWS_CPU_CAPS_3DNOW : 0); 
     192                flags |= (available_cpu_flags & FF_CPU_ALTIVEC ? SWS_CPU_CAPS_ALTIVEC : 0); 
     193#elif defined(HAVE_MMX) 
     194                flags |= SWS_CPU_CAPS_MMX; 
     195#if defined(HAVE_MMX2) 
     196                flags |= SWS_CPU_CAPS_MMX2; 
     197#endif 
     198#elif defined(HAVE_3DNOW) 
     199                flags |= SWS_CPU_CAPS_3DNOW; 
     200#endif 
     201                PixelFormat in_format = PIX_FMT_UYVY422; 
     202 
     203                PixelFormat out_format = PIX_FMT_YUV420P; 
     204                if (cformat == CF_422) { 
     205                    out_format = PIX_FMT_YUV422P; 
     206                } 
     207 
     208                // Accelerated Colour conversion routines 
     209                sws_context = sws_getContext(arrivedFrame->GetWidth(), arrivedFrame->GetHeight(), in_format, 
     210                                             outw, outh, out_format, flags, NULL, NULL, NULL); 
     211                if(sws_context == NULL){ 
     212                    debug_msg("DeckLinkCaptureDelegate: error! cannot allocate memory for swscontext!\n"); 
     213                    return S_FALSE; 
     214                }  
     215            } 
     216 
     217            sws_src[0] = (uint8_t*)videoFrame; 
     218            sws_src[1] = sws_src[2] = NULL; 
     219            sws_src_stride[0] = arrivedFrame->GetRowBytes(); 
     220            sws_src_stride[1] = sws_src_stride[2] = 0; 
     221 
     222            sws_tar[0] = (uint8_t*)mBuffer[mWriteIndex]; 
     223            sws_tar[1] = sws_tar[0] + outw * outh; 
     224            if (cformat == CF_422) { 
     225                sws_tar[2] = sws_tar[1] + outw * outh / 2; 
     226            } else { 
     227                sws_tar[2] = sws_tar[1] + outw * outh / 4; 
     228            } 
     229            sws_tar_stride[0] = outw; 
     230            sws_tar_stride[1] = sws_tar_stride[2] = outw/2; 
     231 
     232            sws_scale(sws_context, sws_src, sws_src_stride, 0, arrivedFrame->GetHeight(), sws_tar, sws_tar_stride); 
     233#else 
    165234            memcpy((void *)(mBuffer[mWriteIndex]), videoFrame, arrivedFrame->GetRowBytes() * arrivedFrame->GetHeight()); 
     235#endif 
    166236 
    167237// fprintf(stderr, "*push* mBuffer[%i] = 0x%lx\n", mWriteIndex, mBuffer[mWriteIndex]); 
     
    176246        return S_OK; 
    177247    } 
    178  
    179248 
    180249private: 
     
    184253    static const int32_t mBufferSize = 4; 
    185254    volatile uint8_t *mBuffer[mBufferSize]; 
     255#ifdef HAVE_SWSCALE 
     256    SwsContext *sws_context; 
     257    uint8_t *sws_src[3]; 
     258    uint8_t *sws_tar[3]; 
     259    int sws_src_stride[3]; 
     260    int sws_tar_stride[3]; 
     261#endif 
     262    int cformat, outw, outh; 
    186263}; 
    187264 
     
    208285    long displayModeWidth_; 
    209286    long displayModeHeight_; 
    210     BMDTimeValue displayModeFrameDuration_; 
    211     BMDTimeScale displayModeTimeScale_; 
    212287 
    213288    DeckLinkCaptureDelegate *delegate_; 
     
    343418    } 
    344419 
    345     strcpy(attr,"format { 420 422 } "); 
    346     strcat(attr,"size { large } "); 
     420    strcpy(attr,"format { 420 422 cif } "); 
     421    strcat(attr,"size { small cif large } "); 
    347422 
    348423    strcat(attr,"port { "); 
     
    456531            return (TCL_OK); 
    457532        } 
     533    } else if (argc == 2) { 
     534        tcl.evalc("set_software_scale_buttons_state"); 
    458535    } 
    459536    return (InputDevice::command(argc, argv)); 
     
    479556    } 
    480557    running_  = 0; 
     558    delegate_ = NULL; 
    481559} 
    482560 
     
    486564 
    487565    if (argc == 3) { 
    488         if (strcmp(argv[1], "decimate") == 0) { 
    489             decimate_ = atoi(argv[2]); 
    490  
     566        if (strcmp(argv[1], "setSoftwareScale") == 0) { 
    491567            if (running_) { 
    492568                stop(); start(); 
    493569            } 
    494570            return (TCL_OK); 
    495         } 
    496  
    497         if (strcmp(argv[1], "port") == 0) { 
     571 
     572        } else if (strcmp(argv[1], "decimate") == 0) { 
     573            decimate_ = atoi(argv[2]); 
     574 
     575            if (running_) { 
     576                stop(); start(); 
     577            } 
     578            return (TCL_OK); 
     579        } else if (strcmp(argv[1], "port") == 0) { 
    498580            IDeckLinkConfiguration *deckLinkConfiguration = NULL; 
    499581            BMDVideoConnection bmdVideoConnection = bmdVideoConnectionHDMI; 
     
    541623         
    542624            return (TCL_OK); 
    543         } 
    544  
    545         if (strcmp(argv[1], "fps") == 0) { 
     625 
     626        } else if (strcmp(argv[1], "fps") == 0) { 
    546627            debug_msg("DecLinkGrabber: fps %s\n",argv[2]); 
    547         } 
    548  
    549         if (strcmp(argv[1], "type") == 0 || strcmp(argv[1], "format") == 0) { 
     628 
     629        } else if (strcmp(argv[1], "type") == 0 || strcmp(argv[1], "format") == 0) { 
    550630 
    551631            IDeckLinkDisplayModeIterator *displayModeIterator = NULL; 
     
    595675                        displayModeWidth_ = displayMode->GetWidth(); 
    596676                        displayModeHeight_ = displayMode->GetHeight(); 
    597                         displayMode->GetFrameRate(&displayModeFrameDuration_, &displayModeTimeScale_); 
    598 fprintf(stderr, "DisplayMode width=%li height=%li frame duration=%li time scale=%li\n", displayModeWidth_, displayModeHeight_,displayModeFrameDuration_,  displayModeTimeScale_); 
    599677                        break; 
    600678                    } 
     
    633711        deckLinkInput_->Release(); 
    634712    } 
     713    if (delegate_ != NULL) { 
     714        delegate_->Release(); 
     715    } 
    635716} 
    636717 
     
    638719{ 
    639720    HRESULT result; 
     721    int flags = TCL_GLOBAL_ONLY; 
     722    Tcl& tcl = Tcl::instance(); 
     723    const char* setSoftwareScale = Tcl_GetVar(tcl.interp(), "setSoftwareScale", flags); 
    640724 
    641725    // Set the image size. 
    642726    switch (decimate_) { 
    643727    case 1: // full-sized 
    644         width_ = displayModeWidth_; 
    645         height_ = displayModeHeight_; 
     728        if (strcmp(setSoftwareScale, "960p") == 0) { 
     729            width_ = int(960 * displayModeWidth_ / displayModeHeight_); 
     730            height_ = 960; 
     731        } else if (strcmp(setSoftwareScale, "720p") == 0) { 
     732            width_ = int(720 * displayModeWidth_ / displayModeHeight_); 
     733            height_ = 720; 
     734        } else if (strcmp(setSoftwareScale, "576p") == 0) { 
     735          width_ = int(576 * displayModeWidth_ / displayModeHeight_); 
     736          height_ = 576; 
     737        } else if (strcmp(setSoftwareScale, "480p") == 0) { 
     738          width_ = int(480 * displayModeWidth_ / displayModeHeight_); 
     739          height_ = 480; 
     740        } else { 
     741          width_ = displayModeWidth_; 
     742          height_ = displayModeHeight_; 
     743        } 
    646744        break; 
    647745    case 2: // CIF-sized 
     
    673771    } 
    674772 
    675     delegate_ = new DeckLinkCaptureDelegate(width_, height_); 
     773    if (delegate_) { 
     774        delegate_->Release(); 
     775    } 
     776    delegate_ = new DeckLinkCaptureDelegate(outw_, outh_, cformat_); 
    676777 
    677778    result = deckLinkInput_->SetCallback(delegate_); 
     
    714815    } 
    715816 
     817    if (!running_) { 
     818        return 0; 
     819    } 
     820 
    716821    uint8_t *fr = delegate_->GetVideoFrame(); 
    717822    if (fr == NULL) { 
     
    719824    } 
    720825 
     826#ifdef HAVE_SWSCALE 
     827    switch (cformat_) { 
     828    case CF_420: 
     829    case CF_CIF: 
     830        memcpy((char *)frame_, (char *)fr, outw_ * outh_ * 3 / 2); 
     831      break; 
     832 
     833    case CF_422: 
     834        memcpy((char *)frame_, (char *)fr, outw_ * outh_ * 2); 
     835      break; 
     836    } 
     837#else 
    721838    switch (cformat_) { 
    722839    case CF_420: 
     
    729846      break; 
    730847    } 
    731  
     848#endif 
    732849    suppress(frame_); 
    733850    saveblks(frame_);