zoukankan      html  css  js  c++  java
  • 基于OpenCV的视频图像组态 (13):VLC Player解码帧数据

    网上示例

    vlc是一套优秀的开源媒体库,其特点是提供了完整的流媒体框架, 用它可以非常方便的实现抓取解码帧的功能。

    与此功能有关的关键API为

    libvlc_video_set_callbacks /*设置回调,用来抓取解码后的帧*/

    libvlc_video_set_format /*设置解码帧的格式 yuv or rgba ?*/

    这个函数将三个函数指针作为参数

    /*callback function, lock the shared memory, and tell vlc

    where to put the output frame data*/

    static void *lock(void *data, void **p_pixels);

     

     

    /*##get the out frame data AND u can save it to file, or sent it

    to a next module*/

    static void unlock(void *data, void *id, void *const *p_pixels);

     

    /*how to display the result frame data, u can let vlc do not pop out the displaying gui via this fuction. */

    static void display(void *data, void *id);

    下面是完整示例子:

    #include "stdafx.h"

    #include <Windows.h>

    #include "vlc/vlc.h"

    #include <vector>

    #include <qmutex>

    #include <sstream>

    #include <qimage>

     

    QMutex g_mutex;

    bool g_isInit = false;

    int IMG_WIDTH = 640;

    int IMG_HEIGHT = 480;

    char in_buffer[640*480*4];

    char out_buffer[640*480*4];

    FILE *local;

    int frameNum = 0;

     

    const char* TestFile = "b040_20170106.dat";

    //////////////////////////////////////////////////////////////////////////

    static void *lock(void *data, void **p_pixels)

    {

    g_mutex.lock();

    *p_pixels = out_buffer; /*tell VLC to put decoded data to this buffer*/

    return 0; /* picture identifier, not needed here */

    }

     

    /*##get the argb picture AND save to file*/

    static void unlock(void *data, void *id, void *const *p_pixels)

    {

    QImage image((unsigned char*)out_buffer,640,480,QImage::Format_ARGB32);

    std::ostringstream oss;

    oss << "d:/img"

    << frameNum

    << ".jpg";

    frameNum++;

    image.save(oss.str().c_str());

    g_mutex.unlock();

    }

     

    static void display(void *data, void *id)

    {

    /* do not display the video */

    (void) data;

    }

     

     

     

    //////////////////////////////////////////////////////////////////////////

    int main(int argc, char* argv[])

    {

    libvlc_instance_t * inst;

    libvlc_media_player_t *mp;

    libvlc_media_t *m;

     

    libvlc_time_t length;

    int wait_time=5000;

     

    /* Load the VLC engine */

    inst = libvlc_new (int(options.size()), options.data());

     

     

    // Configure any transcoding or streaming

    // options for the media source.

    options.clear();

     

    //Create a new item

    //Method 1:

    //m = libvlc_media_new_location (inst, "file:///F:\movie\cuc_ieschool.flv");

    //Screen Capture

    //m = libvlc_media_new_location (inst, "screen://");

    //Method 2:


    m = libvlc_media_new_path (inst, "D:\warehouse\data\615\haze.mp4");

    /* Create a media player playing environment */

    mp = libvlc_media_player_new_from_media (m);

     

     

    /* No need to keep the media now */

    libvlc_media_release (m);

     

    /*##comment the followint 2 lines , if you want the out frame display in screen*/

    libvlc_video_set_callbacks(mp, lock, unlock, display, 0);

    libvlc_video_set_format(mp, "RGBA", IMG_WIDTH, IMG_HEIGHT,IMG_WIDTH*4);

     

    // play the media_player

    libvlc_media_player_play (mp);

     

    //wait until the tracks are created

    _sleep (wait_time);

    length = libvlc_media_player_get_length(mp);

    IMG_WIDTH = libvlc_video_get_width(mp);

    IMG_HEIGHT = libvlc_video_get_height(mp);

    printf("Stream Duration: %ds ",length/1000);

    printf("Resolution: %d x %d ",IMG_WIDTH,IMG_HEIGHT);

     

    //Let it play

    _sleep (length-wait_time);

     

    // Stop playing

    libvlc_media_player_stop (mp);

     

    // Free the media_player

    libvlc_media_player_release (mp);

     

    libvlc_release (inst);

     

    return 0;

    }

     

    改编实现

     

    仔细研究网上代码,最终将VLCWrapper改造一下。

    static void *lock(void *opaque, void **plane) {

        VLCWrapper *vlcWrapper = (VLCWrapper*)opaque;

        vlcWrapper->Lock();

        *plane = vlcWrapper->FMat.data;

        return NULL;

    }

     

    static void unlock(void *opaque, void *pic, void * const *plane) {

        VLCWrapper *vlcWrapper = (VLCWrapper*)opaque;

        vlcWrapper->Draw();

        vlcWrapper->Unlock();

    }

     

    static void display(void *opaque, void *pic) {

        (void)opaque;

    }

     

    void __fastcall VLCWrapper::Lock() {

        EnterCriticalSection(&g_VlcCriticalSection);

    }

     

    void __fastcall VLCWrapper::Unlock() {

        LeaveCriticalSection(&g_VlcCriticalSection);

    }

     

    void __fastcall VLCWrapper::Draw() {

        static int radius = 100; // 测试画一个不断长大的圆

        radius += 3;

        if(radius > 1000)

            radius = 100;

        circle(FMat, cv::Point(100, 100), radius / 10, cv::Scalar(255, 255, 255), 3);

        GlobalOpenCVObject->DrawMat(hWnd, FMat, FDisplayWidth, FDisplayHeight);

    }

     

    演示效果

      

     (因为视频文件大小限制,所以最终生成的帧频为2,导致看起来很不流畅)

     

  • 相关阅读:
    tensorflow (七) k-means
    如何提升开发效率-前端技术选型篇
    Spring AOP详解
    Vue.js学习笔记-入门
    拥抱Vue,抛弃jQuery
    HTML+CSS实现审核流程步骤效果
    测试SpringMVC可能出现的线程安全问题
    CGLib动态创建对象和属性
    jconsole观察jvm中线程及GC情况
    Java NIO学习笔记-Selector
  • 原文地址:https://www.cnblogs.com/drgraph/p/8044811.html
Copyright © 2011-2022 走看看