Switch Controller
Loading...
Searching...
No Matches
VideoFrameSink.h
Go to the documentation of this file.
1#pragma once
2
3#include "FFmpegFrameSink.h"
4
5#include "pch.h"
6
7#include <opencv2/core.hpp>
8#include <opencv2/highgui.hpp>
9#include <opencv2/imgcodecs.hpp>
10#include <opencv2/imgproc.hpp>
11
12extern "C" {
13#include <libavutil/imgutils.h>
14#include <libswscale/swscale.h>
15}
16
18private:
19 int width = 0;
20 int height = 0;
21 AVPixelFormat pixelFormat;
22
23 struct swsContextDeleter {
24 void operator()(SwsContext *s) const noexcept { sws_freeContext(s); }
25 };
26 std::unique_ptr<SwsContext, swsContextDeleter> swsContext;
27 std::vector<uint8_t> data;
28 int linesize[4];
29
30 AVPixelFormat outputPixelFormat = AV_PIX_FMT_BGR24;
31 int outputWidth = 1920;
32 int outputHeight = 1080;
33
34 void virtualInit(AVCodecContext *decoderContext) override {
35 spdlog::info("intitializing VideoFrameSink");
36
37 width = decoderContext->width;
38 height = decoderContext->height;
39 pixelFormat = decoderContext->pix_fmt;
40
41 int res =
42 av_image_fill_linesizes(linesize, outputPixelFormat, outputWidth);
43 if (res < 0) {
44 char error[AV_ERROR_MAX_STRING_SIZE];
45 av_make_error_string(error, AV_ERROR_MAX_STRING_SIZE, res);
46 throw std::runtime_error(
47 "Error getting linesize in VideoFrameSink: " +
48 std::string(error));
49 }
50
51 res = av_image_get_buffer_size(outputPixelFormat, outputWidth,
52 outputHeight, 1);
53 if (res < 0) {
54 char error[AV_ERROR_MAX_STRING_SIZE];
55 av_make_error_string(error, AV_ERROR_MAX_STRING_SIZE, res);
56 throw std::runtime_error(
57 "Error getting plane size in VideoFrameSink: " +
58 std::string(error));
59 }
60 data.resize(static_cast<std::size_t>(res));
61
62 swsContext = {sws_getCachedContext(nullptr, width, height, pixelFormat,
63 outputWidth, outputHeight,
64 outputPixelFormat, 0, nullptr,
65 nullptr, nullptr),
66 swsContextDeleter()};
67 spdlog::info("intitialized VideoFrameSink");
68 }
69
70 void virtualOutputFrame(AVFrame *frame) override {
71 if (frame->width != width || frame->height != height ||
72 frame->format != pixelFormat) {
73 throw std::runtime_error(
74 "Cannot support changing input format in VideoFrameSink");
75 }
76
77 uint8_t *dataPointer = data.data();
78 int res = sws_scale(swsContext.get(), frame->data, frame->linesize, 0,
79 height, &dataPointer, linesize);
80 if (res < 0) {
81 char error[AV_ERROR_MAX_STRING_SIZE];
82 av_make_error_string(error, AV_ERROR_MAX_STRING_SIZE, res);
83 throw std::runtime_error(
84 "Error converting image in VideoFrameSink: " +
85 std::string(error));
86 }
87 }
88
89 void getDataWithoutLock(std::vector<uint8_t> &dataCopy) override {
90 dataCopy.resize(this->data.size());
91 std::copy(this->data.begin(), this->data.end(), dataCopy.begin());
92 }
93
94public:
96
97 AVMediaType getType() const override { return AVMEDIA_TYPE_VIDEO; }
98
99 int getWidth() const { return outputWidth; }
100 int getHeight() const { return outputHeight; }
101};
Definition: FFmpegFrameSink.h:23
Definition: VideoFrameSink.h:17
int getHeight() const
Definition: VideoFrameSink.h:100
AVMediaType getType() const override
Definition: VideoFrameSink.h:97
VideoFrameSink()
Definition: VideoFrameSink.h:95
int getWidth() const
Definition: VideoFrameSink.h:99