LoginSignup
0
0

More than 3 years have passed since last update.

[WinForms(unsafe)] USBカメラの生データを取得する

Last updated at Posted at 2020-07-14
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

using FFmpeg.AutoGen;

using OpenCvSharp;
using OpenCvSharp.Extensions;

namespace FFmpegAutoGenApp
{
    public partial class FormMain : Form
    {
        private CancellationTokenSource _cancel;

        public FormMain()
        {
            InitializeComponent();
        }

        public unsafe void FFmpeg_OpenCV(CancellationToken token)
        {
            AVFormatContext *camera;
            AVPacket packet;

            ffmpeg.avdevice_register_all();
            ffmpeg.avformat_open_input(&camera, "video=YOUR-WEBCAM", ffmpeg.av_find_input_format("dshow"), null);
            ffmpeg.av_init_packet(&packet);

            var codec = camera->streams[0]->codec;
            Mat dest = new Mat(codec->height, codec->width, MatType.CV_8UC3);

            while (token.IsCancellationRequested == false && ffmpeg.av_read_frame(camera, &packet) >= 0)
            {
                Mat source = new Mat(codec->height, codec->width, MatType.CV_8UC2, (IntPtr)packet.data);
                Cv2.CvtColor(source, dest, ColorConversionCodes.YUV2BGR_YUY2);

                Invoke(new Action(() =>
                {
                    pboxView.Image = BitmapConverter.ToBitmap(dest); 
                    pboxView.Update();
                }));

                ffmpeg.av_packet_unref(&packet);
            }

            ffmpeg.avformat_close_input(&camera);
        }

        public unsafe void Only_FFmpeg(CancellationToken token)
        {
            AVFormatContext* camera;
            AVPacket packet;

            ffmpeg.avdevice_register_all();
            ffmpeg.avformat_open_input(&camera, "video=YOUR-WEBCAM", ffmpeg.av_find_input_format("dshow"), null);
            ffmpeg.av_init_packet(&packet);

            var codec = camera->streams[0]->codec;
            var dataSize = ffmpeg.av_image_get_buffer_size(AVPixelFormat.AV_PIX_FMT_BGR24, codec->width, codec->height, 1);
            var dataBGR = ffmpeg.av_malloc((ulong)dataSize);
            var sws = ffmpeg.sws_getContext(codec->width, codec->height, codec->pix_fmt, codec->width, codec->height, AVPixelFormat.AV_PIX_FMT_BGR24, ffmpeg.SWS_FAST_BILINEAR, null, null, null);

            while (token.IsCancellationRequested == false && ffmpeg.av_read_frame(camera, &packet) >= 0)
            {
                var linesize = ffmpeg.av_image_get_linesize(codec->pix_fmt, codec->width, 0);
                var linesizeBGR = ffmpeg.av_image_get_linesize(AVPixelFormat.AV_PIX_FMT_BGR24, codec->width, 0);
                ffmpeg.sws_scale(sws, new[] { packet.data }, new[] { linesize }, 0, codec->height, new[] { (byte*)dataBGR }, new[] { linesizeBGR });

                Invoke(new Action(() =>
                {
                    pboxView.Image = new Bitmap(codec->width, codec->height, linesizeBGR, PixelFormat.Format24bppRgb, (IntPtr)dataBGR);
                    pboxView.Update();
                }));

                ffmpeg.av_packet_unref(&packet);
            }

            ffmpeg.av_free(dataBGR);
            ffmpeg.sws_freeContext(sws);
            ffmpeg.avformat_close_input(&camera);
        }

        private void btnRun_Click(object sender, EventArgs e)
        {
            _cancel = new CancellationTokenSource();
            var token = _cancel.Token;

            Task.Run(() => FFmpeg_OpenCV(token), token);
            //Task.Run(() => Only_FFmpeg(token), token);
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            _cancel.Cancel();
        }
    }
}

FFmpeg.AutoGen @Ruslan-B
OpenCvSharp @shimat

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0