Skip to content

Latest commit

 

History

History
1148 lines (1007 loc) · 39.4 KB

Instructions.MD

File metadata and controls

1148 lines (1007 loc) · 39.4 KB

#Prerequieremts Boost Download Boost from here: https://netix.dl.sourceforge.net/project/boost/boost-binaries/1.75.0/boost_1_75_0-msvc-14.2-64.exe Copy from C:\local\boost_1_67_0\ to C:\Program Files\PothosSDR\boost\

Set your SYSTEM VARIABLES using Rapid Enviroment Editor for example
```
BOOST_INCLUDEDIR    C:\Program Files\PothosSDR\boost
	BOOST_LIBRARYDIR    C:\Program Files\PothosSDR\boost\lib64-msvc-14.2
	BOOST_ROOT          C:\Program Files\PothosSDR\boost\boost
```

SDL1.2 Get it here: http://web.archive.org/web/20191227232250if_/http://libsdl.org/release/SDL-devel-1.2.15-VC.zip Extraxt it somewhere (C:\Program Files\PothosSDR\libsdl for example)

So you can use gr_modtool you need readline module, you install this with: pip install pyreadline (if using linux) or pip install readline if using windows

Then you create your OOT module with: gr_modtool nm video_sdl

If it fails like this: Could not find gr-newmod source dir.

then your gr_modtool is broken so you first need to fix it

the problem is that gr.prefs().get_string('modtool', 'newmod_path', options.srcdir) points to C:\PothosSDR\share\gnuradio\modtool\gr-newmod while it should point to C:\Program Files\PothosSDR\share\gnuradio\modtool\gr-newmod

Go here: C:\Program Files\PothosSDR\lib\python2.7\site-packages\gnuradio\modtool\modtool_newmod.py

change self._srcdir = gr.prefs().get_string('modtool', 'newmod_path', options.srcdir) to self._srcdir = os.environ['GR_PREFIX'].split(os.pathsep)[0] + '\share\gnuradio\modtool\gr-newmod'

Then we need to add our block to this module so we do this like this

gr_modtool add sink_s

you should see something like this

C:\Users\Mitja\Documents\Visual Studio 2017\Projects\SDR\GNURadio blocks\new oot
 module\gr-SDLVideo>gr_modtool add sink_s
GNU Radio module name identified: SDLVideo
Block/code identifier: sink_s
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_strea
m', 'hier', 'noblock')
Enter block type: sink
Language (python/cpp):
Language (python/cpp): cpp
Language: C++
Please specify the copyright holder: GNURadio
Enter valid argument list, including default arguments: double framerate, int width, int height, unsigned int format, int dst_width, int dst_height
Add Python QA code? [Y/n] n
Add C++ QA code? [y/N] n
Adding file 'lib\sink_s_impl.h'...
Adding file 'lib\sink_s_impl.cc'...
Adding file 'include\SDLVideo\sink_s.h'...
Editing swig\SDLVideo_swig.i...
Adding file 'python\qa_sink_s.py'...
Editing python/CMakeLists.txt...
Adding file 'grc\SDLVideo_sink_s.xml'...
Editing grc/CMakeLists.txt...

then goto gr-video_sdl\lib\sink_s_impl.h and add

/* -*- c++ -*- */
/* 
 * Copyright 2022 GNURadio.
 * 
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 * 
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this software; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */

#ifndef INCLUDED_VIDEO_SDL_SINK_S_IMPL_H
#define INCLUDED_VIDEO_SDL_SINK_S_IMPL_H

#include <video_sdl/sink_s.h>
#include <SDL.h>

namespace gr {
namespace video_sdl {

/*  fourcc (four character code) */
#define vid_fourcc(a, b, c, d)                                             \
    (((unsigned)(a) << 0) | ((unsigned)(b) << 8) | ((unsigned)(c) << 16) | \
     ((unsigned)(d) << 24))
#define IMGFMT_YV12 vid_fourcc('Y', 'V', '1', '2') /* 12  YVU 4:2:0 */

class sink_s_impl : public sink_s
{
private:
    int d_chunk_size;

protected:
    void copy_line_pixel_interleaved(unsigned char* dst_pixels_u,
                                     unsigned char* dst_pixels_v,
                                     const short* src_pixels,
                                     int src_width);
    void copy_line_line_interleaved(unsigned char* dst_pixels_u,
                                    unsigned char* dst_pixels_v,
                                    const short* src_pixels,
                                    int src_width);
    void copy_line_single_plane(unsigned char* dst_pixels,
                                const short* src_pixels,
                                int src_width);
    void copy_line_single_plane_dec2(unsigned char* dst_pixels,
                                     const short* src_pixels,
                                     int src_width);
    int copy_plane_to_surface(int plane, int noutput_items, const short* src_pixels);

    float d_framerate;
    int d_wanted_frametime_ms;
    int d_width;
    int d_height;
    int d_dst_width;
    int d_dst_height;
    int d_format;
    int d_current_line;
    SDL_Surface* d_screen;
    SDL_Overlay* d_image;
    SDL_Rect d_dst_rect;
    float d_avg_delay;
    unsigned int d_wanted_ticks;

public:
    sink_s_impl(double framerate,
                int width,
                int height,
                unsigned int format,
                int dst_width,
                int dst_height);
    ~sink_s_impl();

    int work(int noutput_items,
             gr_vector_const_void_star& input_items,
             gr_vector_void_star& output_items);
};

} /* namespace video_sdl */
} /* namespace gr */

#endif /* INCLUDED_VIDEO_SDL_SINK_S_IMPL_H */

also goto gr-video_sdl\lib\sink_s_impl.cc and replace everything with this

/* -*- c++ -*- */
/*
 * Copyright 2006,2010,2012 Free Software Foundation, Inc.
 *
 * This file is part of GNU Radio
 *
 * GNU Radio is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 *
 * GNU Radio is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with GNU Radio; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "sink_s_impl.h"
#include <gnuradio/io_signature.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
#include <stdexcept>


namespace gr {
namespace video_sdl {


sink_s::sptr sink_s::make(double framerate,
                          int width,
                          int height,
                          unsigned int format,
                          int dst_width,
                          int dst_height)
{
    return gnuradio::get_initial_sptr(
        new sink_s_impl(framerate, width, height, format, dst_width, dst_height));
}

sink_s_impl::sink_s_impl(double framerate,
                         int width,
                         int height,
                         unsigned int format,
                         int dst_width,
                         int dst_height)
    : sync_block("video_sdl_sink_s",
                 io_signature::make(1, 3, sizeof(short)),
                 io_signature::make(0, 0, 0)),
      d_chunk_size(width * height),
      d_framerate(framerate),
      d_wanted_frametime_ms(0),
      d_width(width),
      d_height(height),
      d_dst_width(dst_width),
      d_dst_height(dst_height),
      d_format(format),
      d_current_line(0),
      d_screen(NULL),
      d_image(NULL),
      d_avg_delay(0.0),
      d_wanted_ticks(0)
{
    if (framerate <= 0.0)
        d_wanted_frametime_ms = 0; // Go as fast as possible
    else
        d_wanted_frametime_ms = (int)(1000.0 / framerate);

    if (dst_width < 0)
        d_dst_width = d_width;
    if (dst_height < 0)
        d_dst_height = d_height;
    if (0 == format)
        d_format = IMGFMT_YV12;

    atexit(SDL_Quit); // check if this is the way to do this
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        std::cerr << "video_sdl::sink_s: Couldn't initialize SDL:" << SDL_GetError()
                  << " \n SDL_Init(SDL_INIT_VIDEO) failed\n";
        throw std::runtime_error("video_sdl::sink_s");
    };

    /* accept any depth */
    d_screen = SDL_SetVideoMode(
        dst_width,
        dst_height,
        0,
        SDL_SWSURFACE | SDL_RESIZABLE |
            SDL_ANYFORMAT); // SDL_DOUBLEBUF |SDL_SWSURFACE| SDL_HWSURFACE||SDL_FULLSCREEN

    if (d_screen == NULL) {
        std::cerr << "Unable to set SDL video mode: " << SDL_GetError()
                  << "\n SDL_SetVideoMode() Failed \n";
        exit(1);
    }
    if (d_image) {
        SDL_FreeYUVOverlay(d_image);
    }

    /* Initialize and create the YUV Overlay used for video out */
    if (!(d_image =
              SDL_CreateYUVOverlay(d_width, d_height, SDL_YV12_OVERLAY, d_screen))) {
        std::cerr << "SDL: Couldn't create a YUV overlay: \n" << SDL_GetError() << "\n";
        throw std::runtime_error("video_sdl::sink_s");
    }

    printf("SDL screen_mode %d bits-per-pixel\n", d_screen->format->BitsPerPixel);
    printf("SDL overlay_mode %i \n", d_image->format);

    d_chunk_size = (std::min)(1, 16384 / width); // width*16;
    d_chunk_size = d_chunk_size * width;
    // d_chunk_size = (int) (width);
    set_output_multiple(d_chunk_size);

    /* Set the default playback area */
    d_dst_rect.x = 0;
    d_dst_rect.y = 0;
    d_dst_rect.w = d_dst_width;
    d_dst_rect.h = d_dst_height;
    // clear the surface to grey

    if (SDL_LockYUVOverlay(d_image)) {
        std::cerr << "SDL: Couldn't lock YUV overlay: \n" << SDL_GetError() << "\n";
        throw std::runtime_error("video_sdl::sink_s");
    }

    memset(d_image->pixels[0], 128, d_image->pitches[0] * d_height);
    memset(d_image->pixels[1], 128, d_image->pitches[1] * d_height / 2);
    memset(d_image->pixels[2], 128, d_image->pitches[2] * d_height / 2);
    SDL_UnlockYUVOverlay(d_image);
}

sink_s_impl::~sink_s_impl() { SDL_Quit(); }

void sink_s_impl::copy_line_pixel_interleaved(unsigned char* dst_pixels_u,
                                              unsigned char* dst_pixels_v,
                                              const short* src_pixels,
                                              int src_width)
{
    for (int i = 0; i < src_width; i++) {
        dst_pixels_u[i] = (unsigned char)src_pixels[i * 2];
        dst_pixels_v[i] = (unsigned char)src_pixels[i * 2 + 1];
    }
}

void sink_s_impl::copy_line_line_interleaved(unsigned char* dst_pixels_u,
                                             unsigned char* dst_pixels_v,
                                             const short* src_pixels,
                                             int src_width)
{
    for (int i = 0; i < src_width; i++) {
        dst_pixels_u[i] = (unsigned char)src_pixels[i];
        dst_pixels_v[i] = (unsigned char)src_pixels[i + src_width];
    }

    for (int i = src_width; i < src_width * 2; i++) {
        dst_pixels_v[i] = (unsigned char)src_pixels[i];
    }
}

void sink_s_impl::copy_line_single_plane(unsigned char* dst_pixels,
                                         const short* src_pixels,
                                         int src_width)
{
    for (int i = 0; i < src_width; i++) {
        dst_pixels[i] = (unsigned char)src_pixels[i];
    }
}

void sink_s_impl::copy_line_single_plane_dec2(unsigned char* dst_pixels,
                                              const short* src_pixels,
                                              int src_width)
{
    for (int i = 0, j = 0; i < src_width; i += 2, j++) {
        dst_pixels[j] = (unsigned char)src_pixels[i];
    }
}

int sink_s_impl::copy_plane_to_surface(int plane,
                                       int noutput_items,
                                       const short* src_pixels)
{
    const int first_dst_plane = (12 == plane || 1122 == plane) ? 1 : plane;
    const int second_dst_plane = (12 == plane || 1122 == plane) ? 2 : plane;
    int current_line = (0 == plane) ? d_current_line : d_current_line / 2;

    unsigned char* dst_pixels = (unsigned char*)d_image->pixels[first_dst_plane];
    dst_pixels = &dst_pixels[current_line * d_image->pitches[first_dst_plane]];

    unsigned char* dst_pixels_2 = (unsigned char*)d_image->pixels[second_dst_plane];
    dst_pixels_2 = &dst_pixels_2[current_line * d_image->pitches[second_dst_plane]];

    int src_width = (0 == plane || 12 == plane || 1122 == plane) ? d_width : d_width / 2;
    int noutput_items_produced = 0;
    int max_height = (0 == plane) ? d_height - 1 : d_height / 2 - 1;

    for (int i = 0; i < noutput_items; i += src_width) {
        // output one line at a time
        if (12 == plane) {
            copy_line_pixel_interleaved(dst_pixels, dst_pixels_2, src_pixels, src_width);
            dst_pixels_2 += d_image->pitches[second_dst_plane];
        } else if (1122 == plane) {
            copy_line_line_interleaved(dst_pixels, dst_pixels_2, src_pixels, src_width);
            dst_pixels_2 += d_image->pitches[second_dst_plane];
            src_pixels += src_width;
        } else if (0 == plane)
            copy_line_single_plane(dst_pixels, src_pixels, src_width);
        else /* 1==plane || 2==plane*/
            copy_line_single_plane_dec2(
                dst_pixels, src_pixels, src_width); // decimate by two horizontally

        src_pixels += src_width;
        dst_pixels += d_image->pitches[first_dst_plane];
        noutput_items_produced += src_width;
        current_line++;
        if (current_line > max_height) {
            // Start new frame
            // TODO, do this all in a separate thread
            current_line = 0;
            dst_pixels = d_image->pixels[first_dst_plane];
            dst_pixels_2 = d_image->pixels[second_dst_plane];
            if (0 == plane) {
                SDL_DisplayYUVOverlay(d_image, &d_dst_rect);
                // SDL_Flip(d_screen);
                unsigned int ticks = SDL_GetTicks(); // milliseconds
                d_wanted_ticks += d_wanted_frametime_ms;
                float avg_alpha = 0.1;
                int time_diff = d_wanted_ticks - ticks;
                d_avg_delay = time_diff * avg_alpha + d_avg_delay * (1.0 - avg_alpha);
            }
        }
    }

    if (0 == plane)
        d_current_line = current_line;

    return noutput_items_produced;
}

int sink_s_impl::work(int noutput_items,
                      gr_vector_const_void_star& input_items,
                      gr_vector_void_star& output_items)
{
    short *src_pixels_0, *src_pixels_1, *src_pixels_2;
    int noutput_items_produced = 0;
    int plane;
    int delay = (int)d_avg_delay;

    if (0 == d_wanted_ticks)
        d_wanted_ticks = SDL_GetTicks();
    if (delay > 0)
        SDL_Delay((unsigned int)delay); // compensate if running too fast

    if (SDL_LockYUVOverlay(d_image)) {
        return 0;
    }

    switch (input_items.size()) {
    case 3: // first channel=Y, second channel is  U , third channel is V
        src_pixels_0 = (short*)input_items[0];
        src_pixels_1 = (short*)input_items[1];
        src_pixels_2 = (short*)input_items[2];
        for (int i = 0; i < noutput_items; i += d_chunk_size) {
            copy_plane_to_surface(1, d_chunk_size, src_pixels_1);
            copy_plane_to_surface(2, d_chunk_size, src_pixels_2);
            noutput_items_produced +=
                copy_plane_to_surface(0, d_chunk_size, src_pixels_0);
            src_pixels_0 += d_chunk_size;
            src_pixels_1 += d_chunk_size;
            src_pixels_2 += d_chunk_size;
        }
        break;
    case 2:
        if (1) { // if(pixel_interleaved_uv)
            // first channel=Y, second channel is alternating pixels U and V
            src_pixels_0 = (short*)input_items[0];
            src_pixels_1 = (short*)input_items[1];
            for (int i = 0; i < noutput_items; i += d_chunk_size) {
                copy_plane_to_surface(12, d_chunk_size / 2, src_pixels_1);
                noutput_items_produced +=
                    copy_plane_to_surface(0, d_chunk_size, src_pixels_0);
                src_pixels_0 += d_chunk_size;
                src_pixels_1 += d_chunk_size;
            }
        } else {
            // first channel=Y, second channel is alternating lines U and V
            src_pixels_0 = (short*)input_items[0];
            src_pixels_1 = (short*)input_items[1];
            for (int i = 0; i < noutput_items; i += d_chunk_size) {
                copy_plane_to_surface(1222, d_chunk_size / 2, src_pixels_1);
                noutput_items_produced +=
                    copy_plane_to_surface(0, d_chunk_size, src_pixels_0);
                src_pixels_0 += d_chunk_size;
                src_pixels_1 += d_chunk_size;
            }
        }
        break;
    case 1: // grey (Y) input
        /* Y component */
        plane = 0;
        src_pixels_0 = (short*)input_items[plane];
        for (int i = 0; i < noutput_items; i += d_chunk_size) {
            noutput_items_produced +=
                copy_plane_to_surface(plane, d_chunk_size, src_pixels_0);
            src_pixels_0 += d_chunk_size;
        }
        break;
    default: // 0 or more then 3 channels
        std::cerr << "video_sdl::sink_s: Wrong number of channels: ";
        std::cerr
            << "1, 2 or 3 channels are supported.\n  Requested number of channels is "
            << input_items.size() << "\n";
        throw std::runtime_error("video_sdl::sink_s");
    }

    SDL_UnlockYUVOverlay(d_image);
    return noutput_items_produced;
}

} /* namespace video_sdl */
} /* namespace gr */

then add another block

gr_modtool add sink_uc

you should see something like this

C:\Users\Mitja\Documents\Visual Studio 2017\Projects\SDR\GNURadio blocks\new oot
 module\gr-video_sdl>gr_modtool add sink_uc
GNU Radio module name identified: video_sdl
Block/code identifier: sink_uc
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_strea
m', 'hier', 'noblock')
Enter block type: sink
Language (python/cpp): cpp
Language: C++
Please specify the copyright holder: GNURadio
Enter valid argument list, including default arguments: double framerate, int width, int height, unsigned int format, int dst_width, int dst_height
Add Python QA code? [Y/n] n
Add C++ QA code? [Y/n] n
Adding file 'lib\sink_uc_impl.h'...
Adding file 'lib\sink_uc_impl.cc'...
Adding file 'include\video_sdl\sink_uc.h'...
Editing swig\video_sdl_swig.i...
Adding file 'grc\video_sdl_sink_uc.xml'...
Editing grc/CMakeLists.txt...

then goto gr-video_sdl\lib\sink_uc_impl.h and add

#include <SDL.h>

namespace gr {
namespace video_sdl {

/*  fourcc (four character code) */
#define vid_fourcc(a, b, c, d)                                             \
    (((unsigned)(a) << 0) | ((unsigned)(b) << 8) | ((unsigned)(c) << 16) | \
     ((unsigned)(d) << 24))
#define IMGFMT_YV12 vid_fourcc('Y', 'V', '1', '2') /* 12  YVU 4:2:0 */

class sink_uc_impl : public sink_uc
{
private:
    int d_chunk_size;

protected:
    void copy_line_pixel_interleaved(unsigned char* dst_pixels_u,
                                     unsigned char* dst_pixels_v,
                                     const unsigned char* src_pixels,
                                     int src_width);
    void copy_line_line_interleaved(unsigned char* dst_pixels_u,
                                    unsigned char* dst_pixels_v,
                                    const unsigned char* src_pixels,
                                    int src_width);
    void copy_line_single_plane(unsigned char* dst_pixels,
                                const unsigned char* src_pixels,
                                int src_width);
    void copy_line_single_plane_dec2(unsigned char* dst_pixels,
                                     const unsigned char* src_pixels,
                                     int src_width);
    int
    copy_plane_to_surface(int plane, int noutput_items, const unsigned char* src_pixels);

    float d_framerate;
    int d_wanted_frametime_ms;
    int d_width;
    int d_height;
    int d_dst_width;
    int d_dst_height;
    int d_format;
    int d_current_line;
    SDL_Surface* d_screen;
    SDL_Overlay* d_image;
    SDL_Rect d_dst_rect;
    float d_avg_delay;
    unsigned int d_wanted_ticks;

public:
    sink_uc_impl(double framerate,
                 int width,
                 int height,
                 unsigned int format,
                 int dst_width,
                 int dst_height);
    ~sink_uc_impl();

    int work(int noutput_items,
             gr_vector_const_void_star& input_items,
             gr_vector_void_star& output_items);
};

} /* namespace video_sdl */
} /* namespace gr */

#endif /* INCLUDED_VIDEO_SDL_SINK_UC_IMPL_H */

also goto gr-video_sdl\lib\sink_uc_impl.cc and replace everything with this

/* -*- c++ -*- */
/*
 * Copyright 2006,2010,2012 Free Software Foundation, Inc.
 *
 * This file is part of GNU Radio
 *
 * GNU Radio is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 *
 * GNU Radio is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with GNU Radio; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "sink_uc_impl.h"
#include <gnuradio/io_signature.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
#include <stdexcept>


namespace gr {
namespace video_sdl {

sink_uc::sptr sink_uc::make(double framerate,
                            int width,
                            int height,
                            unsigned int format,
                            int dst_width,
                            int dst_height)
{
    return gnuradio::get_initial_sptr(
        new sink_uc_impl(framerate, width, height, format, dst_width, dst_height));
}

sink_uc_impl::sink_uc_impl(double framerate,
                           int width,
                           int height,
                           unsigned int format,
                           int dst_width,
                           int dst_height)
    : sync_block("video_sdl_sink_uc",
                 io_signature::make(1, 3, sizeof(unsigned char)),
                 io_signature::make(0, 0, 0)),
      d_chunk_size(width * height),
      d_framerate(framerate),
      d_wanted_frametime_ms(0),
      d_width(width),
      d_height(height),
      d_dst_width(dst_width),
      d_dst_height(dst_height),
      d_format(format),
      d_current_line(0),
      d_screen(NULL),
      d_image(NULL),
      d_avg_delay(0.0),
      d_wanted_ticks(0)
{
    if (framerate <= 0.0)
        d_wanted_frametime_ms = 0; // Go as fast as possible
    else
        d_wanted_frametime_ms = (int)(1000.0 / framerate);

    if (dst_width < 0)
        d_dst_width = d_width;

    if (dst_height < 0)
        d_dst_height = d_height;

    if (0 == format)
        d_format = IMGFMT_YV12;

    atexit(SDL_Quit); // check if this is the way to do this
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        std::cerr << "video_sdl::sink_uc: Couldn't initialize SDL:" << SDL_GetError()
                  << " \n SDL_Init(SDL_INIT_VIDEO) failed\n";
        throw std::runtime_error("video_sdl::sink_uc");
    }

    /* accept any depth */
    d_screen = SDL_SetVideoMode(
        dst_width,
        dst_height,
        0,
        SDL_SWSURFACE | SDL_RESIZABLE |
            SDL_ANYFORMAT); // SDL_DOUBLEBUF |SDL_SWSURFACE| SDL_HWSURFACE||SDL_FULLSCREEN

    if (d_screen == NULL) {
        std::cerr << "Unable to set SDL video mode: " << SDL_GetError()
                  << "\n SDL_SetVideoMode() Failed \n";
        exit(1);
    }

    if (d_image) {
        SDL_FreeYUVOverlay(d_image);
    }

    /* Initialize and create the YUV Overlay used for video out */
    if (!(d_image =
              SDL_CreateYUVOverlay(d_width, d_height, SDL_YV12_OVERLAY, d_screen))) {
        std::cerr << "SDL: Couldn't create a YUV overlay: \n" << SDL_GetError() << "\n";
        throw std::runtime_error("video_sdl::sink_uc");
    }

    printf("SDL screen_mode %d bits-per-pixel\n", d_screen->format->BitsPerPixel);
    printf("SDL overlay_mode %i \n", d_image->format);

    d_chunk_size = (std::min)(1, 16384 / width); // width*16;
    d_chunk_size = d_chunk_size * width;
    // d_chunk_size = (int)(width);
    set_output_multiple(d_chunk_size);

    /* Set the default playback area */
    d_dst_rect.x = 0;
    d_dst_rect.y = 0;
    d_dst_rect.w = d_dst_width;
    d_dst_rect.h = d_dst_height;
    // clear the surface to grey

    if (SDL_LockYUVOverlay(d_image)) {
        std::cerr << "SDL: Couldn't lock YUV overlay: \n" << SDL_GetError() << "\n";
        throw std::runtime_error("video_sdl::sink_uc");
    }

    memset(d_image->pixels[0], 128, d_image->pitches[0] * d_height);
    memset(d_image->pixels[1], 128, d_image->pitches[1] * d_height / 2);
    memset(d_image->pixels[2], 128, d_image->pitches[2] * d_height / 2);
    SDL_UnlockYUVOverlay(d_image);
}

sink_uc_impl::~sink_uc_impl() { SDL_Quit(); }

void sink_uc_impl::copy_line_pixel_interleaved(unsigned char* dst_pixels_u,
                                               unsigned char* dst_pixels_v,
                                               const unsigned char* src_pixels,
                                               int src_width)
{
    for (int i = 0; i < src_width; i++) {
        dst_pixels_u[i] = src_pixels[i * 2];
        dst_pixels_v[i] = src_pixels[i * 2 + 1];
    }
}

void sink_uc_impl::copy_line_line_interleaved(unsigned char* dst_pixels_u,
                                              unsigned char* dst_pixels_v,
                                              const unsigned char* src_pixels,
                                              int src_width)
{
    memcpy(dst_pixels_u, src_pixels, src_width);
    memcpy(dst_pixels_v, src_pixels + src_width, src_width);
}

void sink_uc_impl::copy_line_single_plane(unsigned char* dst_pixels,
                                          const unsigned char* src_pixels,
                                          int src_width)
{
    memcpy(dst_pixels, src_pixels, src_width);
}

void sink_uc_impl::copy_line_single_plane_dec2(unsigned char* dst_pixels,
                                               const unsigned char* src_pixels,
                                               int src_width)
{
    for (int i = 0, j = 0; i < src_width; i += 2, j++) {
        dst_pixels[j] = (unsigned char)src_pixels[i];
    }
}

int sink_uc_impl::copy_plane_to_surface(int plane,
                                        int noutput_items,
                                        const unsigned char* src_pixels)
{
    const int first_dst_plane = (12 == plane || 1122 == plane) ? 1 : plane;
    const int second_dst_plane = (12 == plane || 1122 == plane) ? 2 : plane;
    int current_line = (0 == plane) ? d_current_line : d_current_line / 2;

    unsigned char* dst_pixels = (unsigned char*)d_image->pixels[first_dst_plane];
    dst_pixels = &dst_pixels[current_line * d_image->pitches[first_dst_plane]];

    unsigned char* dst_pixels_2 = (unsigned char*)d_image->pixels[second_dst_plane];
    dst_pixels_2 = &dst_pixels_2[current_line * d_image->pitches[second_dst_plane]];

    int src_width = (0 == plane || 12 == plane || 1122 == plane) ? d_width : d_width / 2;
    int noutput_items_produced = 0;
    int max_height = (0 == plane) ? d_height - 1 : d_height / 2 - 1;

    for (int i = 0; i < noutput_items; i += src_width) {
        // output one line at a time
        if (12 == plane) {
            copy_line_pixel_interleaved(dst_pixels, dst_pixels_2, src_pixels, src_width);
            dst_pixels_2 += d_image->pitches[second_dst_plane];
        } else if (1122 == plane) {
            copy_line_line_interleaved(dst_pixels, dst_pixels_2, src_pixels, src_width);
            dst_pixels_2 += d_image->pitches[second_dst_plane];
            src_pixels += src_width;
        } else if (0 == plane)
            copy_line_single_plane(dst_pixels, src_pixels, src_width);
        else /* 1==plane || 2==plane*/
            copy_line_single_plane_dec2(
                dst_pixels, src_pixels, src_width); // decimate by two horizontally

        src_pixels += src_width;
        dst_pixels += d_image->pitches[first_dst_plane];
        noutput_items_produced += src_width;
        current_line++;

        if (current_line > max_height) {
            // Start new frame
            // TODO, do this all in a separate thread
            current_line = 0;
            dst_pixels = d_image->pixels[first_dst_plane];
            dst_pixels_2 = d_image->pixels[second_dst_plane];
            if (0 == plane) {
                SDL_DisplayYUVOverlay(d_image, &d_dst_rect);
                // SDL_Flip(d_screen);
                unsigned int ticks = SDL_GetTicks(); // milliseconds
                d_wanted_ticks += d_wanted_frametime_ms;
                float avg_alpha = 0.1;
                int time_diff = d_wanted_ticks - ticks;
                d_avg_delay = time_diff * avg_alpha + d_avg_delay * (1.0 - avg_alpha);
            }
        }
    }

    if (0 == plane)
        d_current_line = current_line;

    return noutput_items_produced;
}

int sink_uc_impl::work(int noutput_items,
                       gr_vector_const_void_star& input_items,
                       gr_vector_void_star& output_items)
{
    unsigned char *src_pixels_0, *src_pixels_1, *src_pixels_2;
    int noutput_items_produced = 0;
    int plane;
    int delay = (int)d_avg_delay;

    if (0 == d_wanted_ticks)
        d_wanted_ticks = SDL_GetTicks();

    if (delay > 0)
        SDL_Delay((unsigned int)delay); // compensate if running too fast

    if (SDL_LockYUVOverlay(d_image)) {
        return 0;
    }

    switch (input_items.size()) {
    case 3: // first channel=Y, second channel is  U , third channel is V
        src_pixels_0 = (unsigned char*)input_items[0];
        src_pixels_1 = (unsigned char*)input_items[1];
        src_pixels_2 = (unsigned char*)input_items[2];
        for (int i = 0; i < noutput_items; i += d_chunk_size) {
            copy_plane_to_surface(1, d_chunk_size, src_pixels_1);
            copy_plane_to_surface(2, d_chunk_size, src_pixels_2);
            noutput_items_produced +=
                copy_plane_to_surface(0, d_chunk_size, src_pixels_0);
            src_pixels_0 += d_chunk_size;
            src_pixels_1 += d_chunk_size;
            src_pixels_2 += d_chunk_size;
        }
        break;
    case 2:
        if (1) { // if(pixel_interleaved_uv)
            // first channel=Y, second channel is alternating pixels U and V
            src_pixels_0 = (unsigned char*)input_items[0];
            src_pixels_1 = (unsigned char*)input_items[1];
            for (int i = 0; i < noutput_items; i += d_chunk_size) {
                copy_plane_to_surface(12, d_chunk_size / 2, src_pixels_1);
                noutput_items_produced +=
                    copy_plane_to_surface(0, d_chunk_size, src_pixels_0);
                src_pixels_0 += d_chunk_size;
                src_pixels_1 += d_chunk_size;
            }
        } else {
            // first channel=Y, second channel is alternating lines U and V
            src_pixels_0 = (unsigned char*)input_items[0];
            src_pixels_1 = (unsigned char*)input_items[1];
            for (int i = 0; i < noutput_items; i += d_chunk_size) {
                copy_plane_to_surface(1222, d_chunk_size / 2, src_pixels_1);
                noutput_items_produced +=
                    copy_plane_to_surface(0, d_chunk_size, src_pixels_0);
                src_pixels_0 += d_chunk_size;
                src_pixels_1 += d_chunk_size;
            }
        }
        break;
    case 1: // grey (Y) input
        /* Y component */
        plane = 0;
        src_pixels_0 = (unsigned char*)input_items[plane];
        for (int i = 0; i < noutput_items; i += d_chunk_size) {
            noutput_items_produced +=
                copy_plane_to_surface(plane, d_chunk_size, src_pixels_0);
            src_pixels_0 += d_chunk_size;
        }
        break;
    default: // 0 or more then 3 channels
        std::cerr << "video_sdl::sink_uc: Wrong number of channels: ";
        std::cerr
            << "1, 2 or 3 channels are supported.\n  Requested number of channels is "
            << input_items.size() << "\n";
        throw std::runtime_error("video_sdl::sink_uc");
    }

    SDL_UnlockYUVOverlay(d_image);
    return noutput_items_produced;
}

} /* namespace video_sdl */
} /* namespace gr */

then edit gr-video_sdl\lib\CMakeLists.txt and replace with

# Copyright 2011,2012,2016 Free Software Foundation, Inc.
#
# This file was generated by gr_modtool, a tool from the GNU Radio framework
# This file is a part of gr-video_sdl
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING.  If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.

########################################################################
# Setup library
########################################################################
include(GrPlatform) #define LIB_SUFFIX

include_directories(${Boost_INCLUDE_DIR} ${SDL_INCLUDE_DIR})
link_directories(${Boost_LIBRARY_DIRS} ${SDL_LIBRARY})

list(APPEND video_sdl_sources
    sink_s_impl.cc
    sink_uc_impl.cc
)

set(video_sdl_sources "${video_sdl_sources}" PARENT_SCOPE)
if(NOT video_sdl_sources)
	MESSAGE(STATUS "No C++ sources... skipping lib/")
	return()
endif(NOT video_sdl_sources)

add_library(gnuradio-video_sdl SHARED ${video_sdl_sources})
target_link_libraries(gnuradio-video_sdl ${Boost_LIBRARIES} ${GNURADIO_ALL_LIBRARIES})
set_target_properties(gnuradio-video_sdl PROPERTIES DEFINE_SYMBOL "gnuradio_video_sdl_EXPORTS")

if(APPLE)
    set_target_properties(gnuradio-video_sdl PROPERTIES
        INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib"
    )
endif(APPLE)

########################################################################
# Install built library files
########################################################################
include(GrMiscUtils)
GR_LIBRARY_FOO(gnuradio-video_sdl RUNTIME_COMPONENT "video_sdl_runtime" DEVEL_COMPONENT "video_sdl_devel")

########################################################################
# Build and register unit test
########################################################################
include(GrTest)

include_directories(${CPPUNIT_INCLUDE_DIRS})

list(APPEND test_video_sdl_sources
    ${CMAKE_CURRENT_SOURCE_DIR}/test_video_sdl.cc
    ${CMAKE_CURRENT_SOURCE_DIR}/qa_video_sdl.cc
)

add_executable(test-video_sdl ${test_video_sdl_sources})

target_link_libraries(
  test-video_sdl
  ${GNURADIO_RUNTIME_LIBRARIES}
  ${Boost_LIBRARIES}
  ${CPPUNIT_LIBRARIES}
  gnuradio-video_sdl
)

GR_ADD_TEST(test_video_sdl test-video_sdl)

########################################################################
# Print summary
########################################################################
message(STATUS "Using install prefix: ${CMAKE_INSTALL_PREFIX}")
message(STATUS "Building for version: ${VERSION} / ${LIBVER}")

Then we need to add the UI to our block so

go to gr-video_sdl\grc\video_sdl_sink_s.xml and replace with

<?xml version='1.0'?>
<block>
    <name>Video SDL Sink</name>
    <key>video_sdl_sink_s</key>
	<category>[Video]</category>
    <import>from gnuradio import video_sdl</import>
    <make>video_sdl.sink_$(type.fcn)($fps, $width, $height, 0, $display_width, $display_height)</make>
    <param>
        <name>Input Type</name>
        <key>type</key>
        <type>enum</type>
        <option>
            <name>Byte</name>
            <key>byte</key>
            <opt>fcn:uc</opt>
        </option>
        <option>
            <name>Short</name>
            <key>short</key>
            <opt>fcn:s</opt>
        </option>
    </param>
    <param>
        <name>Input Width</name>
        <key>width</key>
        <value>640</value>
        <type>int</type>
    </param>
    <param>
        <name>Input Height</name>
        <key>height</key>
        <value>480</value>
        <type>int</type>
    </param>
    <param>
        <name>Display Width</name>
        <key>display_width</key>
        <value>640</value>
        <type>int</type>
    </param>
    <param>
        <name>Display Height</name>
        <key>display_height</key>
        <value>480</value>
        <type>int</type>
    </param>
    <param>
        <name>Framerate</name>
        <key>fps</key>
        <value>0</value>
        <type>float</type>
    </param>
    <param>
        <name>Channels</name>
        <key>num_channels</key>
        <type>enum</type>
        <option>
            <name>1 (Grayscale)</name>
            <key>1</key>
        </option>
        <option>
            <name>2 (Y, alternating pixels U and V)</name>
            <key>2</key>
        </option>
        <option>
            <name>3 (YUV)</name>
            <key>3</key>
        </option>
    </param>
    <sink>
        <name>in</name>
        <type>$type</type>
        <vlen>1</vlen>
        <nports>$num_channels</nports>
    </sink>
    <doc>
Provides a rudimentary on-screen video display using libsdl.

A framerate of zero means video will be displayed as quickly as possible.

In 1-channel mode, input data is assumed to be grayscale, with each input item mapping to a single pixel.

In 2-channel mode, the first channel is Y for every pixel while the second channel alternates between pixels values for U and V.

In 3-channel mode, input channels are assumed to be matching triples of YUV values, one byte per pixel, per channel.
    </doc>
</block>

the last steps

cd gr-video_sdl
mkdir windows
git clone https://github.com/robinrowe/libunistd.git

edit your main CMakeLists.txt and add under include this

${CMAKE_SOURCE_DIR}/windows/libunistd/unistd

so your include looks something like this

########################################################################
# Setup the include and linker paths
########################################################################
include_directories(
    ${CMAKE_SOURCE_DIR}/lib
    ${CMAKE_SOURCE_DIR}/include
    ${CMAKE_BINARY_DIR}/lib
    ${CMAKE_BINARY_DIR}/include
    ${Boost_INCLUDE_DIRS}
    ${CPPUNIT_INCLUDE_DIRS}
    ${GNURADIO_ALL_INCLUDE_DIRS}
	${CMAKE_SOURCE_DIR}/windows/libunistd/unistd
)

then we build our block like this

cd gr-video_sdl
mkdir build
cd build
cmake ../ -G "Visual Studio 16 2019" -DSDL_LIBRARY="C:\Program Files\PothosSDR\libsdl\lib\x64" -DSDL_INCLUDE_DIR="C:\Program Files\PothosSDR\libsdl\include" -DBOOST_ROOT=${BOOST_ROOT} -DBOOST_LIBRARYDIR=${BOOST_LIBRARYDIR} -DCPPUNIT_INCLUDE_DIRS=${CPPUNIT_INCLUDE_DIRS} -DCPPUNIT_LIBRARIES=${CPPUNIT_LIBRARIES}
msbuild gr-video_sdl.sln 
Pray it will work.....

and Hopefully you can enjoy using your new block now