Refactoring to remove the FavouriteFormat static member
This commit is contained in:
parent
341b60c9d0
commit
ab145e2bb0
5 changed files with 40 additions and 30 deletions
|
@ -6,19 +6,6 @@ extern "C" {
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace mgs::ffmpeg {
|
namespace mgs::ffmpeg {
|
||||||
namespace {
|
|
||||||
::AVPixelFormat get_favourite_format_ifp (::AVCodecContext* s, const ::AVPixelFormat* fmt) {
|
|
||||||
const ::AVPixelFormat* curr_fmt = fmt;
|
|
||||||
const auto fav_format = static_cast<::AVPixelFormat>(Decoder::FavouriteFormat);
|
|
||||||
while (*curr_fmt != -1) {
|
|
||||||
if (*curr_fmt == fav_format)
|
|
||||||
return fav_format;
|
|
||||||
++curr_fmt;
|
|
||||||
}
|
|
||||||
return ::avcodec_default_get_format(s, fmt);
|
|
||||||
}
|
|
||||||
} //unnamed namespace
|
|
||||||
|
|
||||||
AVCodec::AVCodec (::AVCodecID id) :
|
AVCodec::AVCodec (::AVCodecID id) :
|
||||||
m_avcodec(::avcodec_find_decoder(id))
|
m_avcodec(::avcodec_find_decoder(id))
|
||||||
{
|
{
|
||||||
|
@ -28,7 +15,7 @@ AVCodec::AVCodec (::AVCodecID id) :
|
||||||
|
|
||||||
AVCodec::~AVCodec() noexcept = default;
|
AVCodec::~AVCodec() noexcept = default;
|
||||||
|
|
||||||
Decoder AVCodec::make_decoder (unsigned int width, unsigned int height) {
|
Decoder AVCodec::make_decoder (unsigned int width, unsigned int height, ::AVPixelFormat dst_format) {
|
||||||
::AVCodec* const codec = m_avcodec.get();
|
::AVCodec* const codec = m_avcodec.get();
|
||||||
Decoder::UniqueAVCodecContext context{::avcodec_alloc_context3(codec)};
|
Decoder::UniqueAVCodecContext context{::avcodec_alloc_context3(codec)};
|
||||||
if (not context)
|
if (not context)
|
||||||
|
@ -40,12 +27,11 @@ Decoder AVCodec::make_decoder (unsigned int width, unsigned int height) {
|
||||||
|
|
||||||
context->width = width;
|
context->width = width;
|
||||||
context->height = height;
|
context->height = height;
|
||||||
context->get_format = &get_favourite_format_ifp;
|
|
||||||
|
|
||||||
if (::avcodec_open2(context.get(), codec, nullptr) < 0)
|
if (::avcodec_open2(context.get(), codec, nullptr) < 0)
|
||||||
throw std::runtime_error("Could not open codec");
|
throw std::runtime_error("Could not open codec");
|
||||||
|
|
||||||
return {std::move(context)};
|
return {std::move(context), dst_format};
|
||||||
}
|
}
|
||||||
|
|
||||||
} //namespace mgs::ffmpeg
|
} //namespace mgs::ffmpeg
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "avdeleter.hpp"
|
#include "avdeleter.hpp"
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <libavcodec/codec_id.h>
|
#include <libavcodec/codec_id.h>
|
||||||
|
#include <libavutil/pixfmt.h>
|
||||||
} //extern C
|
} //extern C
|
||||||
|
|
||||||
namespace mgs::ffmpeg {
|
namespace mgs::ffmpeg {
|
||||||
|
@ -14,7 +15,7 @@ public:
|
||||||
explicit AVCodec (::AVCodecID id);
|
explicit AVCodec (::AVCodecID id);
|
||||||
~AVCodec() noexcept;
|
~AVCodec() noexcept;
|
||||||
|
|
||||||
Decoder make_decoder (unsigned int width, unsigned int height);
|
Decoder make_decoder (unsigned int width, unsigned int height, ::AVPixelFormat dst_format);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unique_av_ptr<struct ::AVCodec> m_avcodec;
|
unique_av_ptr<struct ::AVCodec> m_avcodec;
|
||||||
|
|
|
@ -12,16 +12,32 @@ extern "C" {
|
||||||
namespace mgs::ffmpeg {
|
namespace mgs::ffmpeg {
|
||||||
namespace {
|
namespace {
|
||||||
constexpr int Align = 32;
|
constexpr int Align = 32;
|
||||||
|
|
||||||
|
::AVPixelFormat get_favourite_format_ifp (::AVCodecContext* s, const ::AVPixelFormat* fmt) {
|
||||||
|
assert(s->opaque);
|
||||||
|
|
||||||
|
const ::AVPixelFormat* curr_fmt = fmt;
|
||||||
|
const auto fav_format = static_cast<const Decoder*>(s->opaque)->destination_format();
|
||||||
|
while (*curr_fmt != -1) {
|
||||||
|
if (*curr_fmt == fav_format)
|
||||||
|
return fav_format;
|
||||||
|
++curr_fmt;
|
||||||
|
}
|
||||||
|
return ::avcodec_default_get_format(s, fmt);
|
||||||
|
}
|
||||||
|
|
||||||
} //unnamed namespace
|
} //unnamed namespace
|
||||||
|
|
||||||
const int Decoder::FavouriteFormat = static_cast<int>(::AVPixelFormat::AV_PIX_FMT_RGB24);
|
Decoder::Decoder (UniqueAVCodecContext&& context, ::AVPixelFormat dst_format) :
|
||||||
|
|
||||||
Decoder::Decoder (UniqueAVCodecContext&& context) :
|
|
||||||
m_context(std::move(context)),
|
m_context(std::move(context)),
|
||||||
m_packet(::av_packet_alloc()),
|
m_packet(::av_packet_alloc()),
|
||||||
m_frame1(::av_frame_alloc()),
|
m_frame1(::av_frame_alloc()),
|
||||||
m_frame2(::av_frame_alloc())
|
m_frame2(::av_frame_alloc()),
|
||||||
|
m_dst_format(dst_format)
|
||||||
{
|
{
|
||||||
|
assert(not m_context->opaque);
|
||||||
|
m_context->opaque = this;
|
||||||
|
m_context->get_format = &get_favourite_format_ifp;
|
||||||
}
|
}
|
||||||
|
|
||||||
Decoder::~Decoder() noexcept = default;
|
Decoder::~Decoder() noexcept = default;
|
||||||
|
@ -50,7 +66,7 @@ std::size_t Decoder::decode (const std::uint8_t* input, std::size_t input_size,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const std::size_t new_out_size = ::av_image_get_buffer_size(
|
const std::size_t new_out_size = ::av_image_get_buffer_size(
|
||||||
static_cast<::AVPixelFormat>(FavouriteFormat),
|
m_dst_format,
|
||||||
m_context->width,
|
m_context->width,
|
||||||
m_context->height,
|
m_context->height,
|
||||||
Align
|
Align
|
||||||
|
@ -69,12 +85,16 @@ std::size_t Decoder::decode (const std::uint8_t* input, std::size_t input_size,
|
||||||
const std::size_t out_size_safe = std::min(out_size, new_out_size);
|
const std::size_t out_size_safe = std::min(out_size, new_out_size);
|
||||||
std::copy(m_frame2->data[0], m_frame2->data[0] + out_size_safe, out);
|
std::copy(m_frame2->data[0], m_frame2->data[0] + out_size_safe, out);
|
||||||
|
|
||||||
return out_size_safe;
|
return new_out_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
::AVPixelFormat Decoder::destination_format() const noexcept {
|
||||||
|
return m_dst_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Decoder::init_sws_context() {
|
void Decoder::init_sws_context() {
|
||||||
const std::size_t new_out_size = ::av_image_get_buffer_size(
|
const std::size_t new_out_size = ::av_image_get_buffer_size(
|
||||||
static_cast<::AVPixelFormat>(FavouriteFormat),
|
m_dst_format,
|
||||||
m_context->width,
|
m_context->width,
|
||||||
m_context->height,
|
m_context->height,
|
||||||
Align
|
Align
|
||||||
|
@ -91,7 +111,7 @@ void Decoder::init_sws_context() {
|
||||||
m_context->pix_fmt, //AV_PIX_FMT_YUVJ422P, //AVPixelFormat src_format
|
m_context->pix_fmt, //AV_PIX_FMT_YUVJ422P, //AVPixelFormat src_format
|
||||||
m_context->width, //int dst_width
|
m_context->width, //int dst_width
|
||||||
m_context->height, //int dst_height
|
m_context->height, //int dst_height
|
||||||
static_cast<::AVPixelFormat>(FavouriteFormat), //AVPixelFormat dst_format
|
m_dst_format, //AVPixelFormat dst_format
|
||||||
SWS_FAST_BILINEAR, //int flags
|
SWS_FAST_BILINEAR, //int flags
|
||||||
nullptr, //SwsFilter* src_filter
|
nullptr, //SwsFilter* src_filter
|
||||||
nullptr, //SwsFilter* dst_filter
|
nullptr, //SwsFilter* dst_filter
|
||||||
|
@ -102,7 +122,7 @@ void Decoder::init_sws_context() {
|
||||||
m_frame2->data,
|
m_frame2->data,
|
||||||
m_frame2->linesize,
|
m_frame2->linesize,
|
||||||
m_frame2_mem.get(),
|
m_frame2_mem.get(),
|
||||||
static_cast<::AVPixelFormat>(FavouriteFormat),
|
m_dst_format,
|
||||||
m_context->width,
|
m_context->width,
|
||||||
m_context->height,
|
m_context->height,
|
||||||
Align
|
Align
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
#include "avdeleter.hpp"
|
#include "avdeleter.hpp"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
extern "C" {
|
||||||
|
#include <libavutil/pixfmt.h>
|
||||||
|
} //extern C
|
||||||
|
|
||||||
namespace mgs::ffmpeg {
|
namespace mgs::ffmpeg {
|
||||||
class Decoder {
|
class Decoder {
|
||||||
|
@ -13,11 +16,10 @@ public:
|
||||||
typedef unique_av_ptr<struct ::SwsContext> UniqueSwsContext;
|
typedef unique_av_ptr<struct ::SwsContext> UniqueSwsContext;
|
||||||
typedef unique_av_ptr<std::uint8_t> UniqueAVMem;
|
typedef unique_av_ptr<std::uint8_t> UniqueAVMem;
|
||||||
|
|
||||||
static const int FavouriteFormat;
|
Decoder (UniqueAVCodecContext&& context, ::AVPixelFormat dst_format);
|
||||||
|
|
||||||
Decoder (UniqueAVCodecContext&& context);
|
|
||||||
~Decoder() noexcept;
|
~Decoder() noexcept;
|
||||||
std::size_t decode (const std::uint8_t* input, std::size_t input_size, std::uint8_t* out, std::size_t out_size);
|
std::size_t decode (const std::uint8_t* input, std::size_t input_size, std::uint8_t* out, std::size_t out_size);
|
||||||
|
::AVPixelFormat destination_format() const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init_sws_context();
|
void init_sws_context();
|
||||||
|
@ -28,5 +30,6 @@ private:
|
||||||
UniqueAVFrame m_frame1;
|
UniqueAVFrame m_frame1;
|
||||||
UniqueAVFrame m_frame2;
|
UniqueAVFrame m_frame2;
|
||||||
UniqueSwsContext m_sws_context;
|
UniqueSwsContext m_sws_context;
|
||||||
|
::AVPixelFormat m_dst_format;
|
||||||
};
|
};
|
||||||
} //namespace mgs::ffmpeg
|
} //namespace mgs::ffmpeg
|
||||||
|
|
|
@ -48,7 +48,7 @@ int main() {
|
||||||
|
|
||||||
mgs::ffmpeg::AVCodec avcodec{::AVCodecID::AV_CODEC_ID_MJPEG};
|
mgs::ffmpeg::AVCodec avcodec{::AVCodecID::AV_CODEC_ID_MJPEG};
|
||||||
auto cam_frame_format = cam.frame_size();
|
auto cam_frame_format = cam.frame_size();
|
||||||
auto decoder{avcodec.make_decoder(cam_frame_format.width, cam_frame_format.height)};
|
auto decoder{avcodec.make_decoder(cam_frame_format.width, cam_frame_format.height, ::AVPixelFormat::AV_PIX_FMT_RGB24)};
|
||||||
|
|
||||||
print_supported_frame_formats(cam);
|
print_supported_frame_formats(cam);
|
||||||
cam.start_streaming();
|
cam.start_streaming();
|
||||||
|
|
Loading…
Add table
Reference in a new issue