Valkka  1.6.1
OpenSource Video Management
hwdecoder.h
1 #ifndef AVHwDecoder_HEADER_GUARD
2 #define AVHwDecoder_HEADER_GUARD
3 /*
4  * AVHwDecoder.h :
5  *
6  * (c) Copyright 2017-2024 Sampsa Riikonen
7  *
8  * Authors: Sampsa Riikonen <sampsa.riikonen@iki.fi>
9  *
10  * This file is part of the Valkka library.
11  *
12  * Valkka is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU Affero General Public License as
14  * published by the Free Software Foundation, either version 3 of the
15  * License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU Affero General Public License for more details.
21  *
22  * You should have received a copy of the GNU Affero General Public License
23  * along with this program. If not, see <https://www.gnu.org/licenses/>
24  *
25  */
26 
36 #include "decoder.h"
37 extern "C" {
38 #include <libavutil/hwcontext.h>
39 }
40 
41 
42 static enum AVPixelFormat find_fmt_by_hw_type(const enum AVHWDeviceType type)
43 {
44  enum AVPixelFormat fmt;
45  switch (type) {
46  case AV_HWDEVICE_TYPE_VAAPI:
47  fmt = AV_PIX_FMT_VAAPI;
48  break;
49  case AV_HWDEVICE_TYPE_DXVA2:
50  fmt = AV_PIX_FMT_DXVA2_VLD;
51  break;
52  case AV_HWDEVICE_TYPE_D3D11VA:
53  fmt = AV_PIX_FMT_D3D11;
54  break;
55  case AV_HWDEVICE_TYPE_VDPAU:
56  fmt = AV_PIX_FMT_VDPAU;
57  break;
58  case AV_HWDEVICE_TYPE_VIDEOTOOLBOX:
59  fmt = AV_PIX_FMT_VIDEOTOOLBOX;
60  break;
61  default:
62  fmt = AV_PIX_FMT_NONE;
63  break;
64  }
65  return fmt;
66 }
67 
68 static enum AVPixelFormat get_vaapi_format(AVCodecContext *ctx,
69  const enum AVPixelFormat *pix_fmts)
70 {
71  // AVCodecContext uses this function:
72  // it gives it a list of AVPixelFormat s
73  // and then this function returns the most relevant one
74  const enum AVPixelFormat *p;
75  // https://ffmpeg.org/doxygen/3.4/pixfmt_8h.html
76  for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) {
77  // std::cout << "hwdecoder.h : trying pix fmt : " << *p << std::endl;
78  switch (*p) {
79  case AV_PIX_FMT_VAAPI_MOCO:
80  //std::cout << "MOCO" << std::endl;
81  break;
82  case AV_PIX_FMT_VAAPI_IDCT:
83  //std::cout << "IDCT" << std::endl;
84  break;
85  /*
86  case AV_PIX_FMT_VAAPI_VLD:
87  // std::cout << "VLD" << std::endl;
88  return *p;
89  // break;
90  */
91  case AV_PIX_FMT_YUVJ420P:
92  // ok: sometimes the vaapi hw decoder
93  // requests this one - what does it mean?
94  // std::cout << "420P" << std::endl;
95  // if we return this, then the decoder won't work .. eh
96  // return *p;
97  break;
98  case AV_PIX_FMT_VAAPI: // same as VLD
99  // std::cout << "OK!" << std::endl;
100  return *p;
101  } // switch
102  }
103  avthreadlogger.log(LogLevel::fatal) << "hwdecoder.h : get_vaapi_format : Unable to decode this stream using VA-API" << std::endl;
104  // TODO: why vaapi can't find correct pix fmt. Could copy all that crap from ffmpeg.c, but it's pretty complicated
105  // offers pix fmts 12, 53 ..
106  return AV_PIX_FMT_NONE;
107 }
108 
125 class AVHwDecoder : public Decoder
126 {
127 
128 public:
129  AVHwDecoder(AVCodecID av_codec_id, AVHWDeviceType hwtype, int n_threads = 1);
130  virtual ~AVHwDecoder();
131 
132 protected:
133  int n_threads;
134  bool active;
135 
136 public:
137  AVCodecID av_codec_id;
138  AVPacket *av_packet;
139  AVCodecContext *av_codec_context;
140  AVCodec *av_codec;
141  AVBufferRef* hw_device_ctx;
142  AVFrame *hw_frame;
143  AVPixelFormat hw_pix_format;
144 
145 public:
146  // needs virtual void output, virtual void pull
147  virtual void flush();
148  virtual bool isOk();
149 
150 };
151 
153 {
154 
155 public:
156  HwVideoDecoder(AVCodecID av_codec_id, AVHWDeviceType hwtype, int n_threads = 1);
157  virtual ~HwVideoDecoder();
158 
159 protected:
160  AVBitmapFrame out_frame;
161  int width;
162  int height;
163  AVFrame *aux_av_frame;
164  AVPixelFormat current_pixel_format;
165  SwsContext *sws_ctx;
166  float secs_per_frame;
167  int error_count;
168 
169 public:
170  virtual Frame *output();
171  virtual bool pull();
172 
173 };
174 
175 
176 // as per: https://www.mail-archive.com/ffmpeg-user@ffmpeg.org/msg30274.html
177 #ifdef av_err2str
178 #undef av_err2str
179 #include <string>
180 av_always_inline std::string av_err2string(int errnum) {
181  char str[AV_ERROR_MAX_STRING_SIZE];
182  return av_make_error_string(str, AV_ERROR_MAX_STRING_SIZE, errnum);
183 }
184 #define av_err2str(err) av_err2string(err).c_str()
185 #endif // av_err2str
186 
187 
188 #endif
Decoded YUV/RGB frame in FFMpeg format.
Definition: frame.h:361
Video decoder using FFmpeg/libav with VAAPI.
Definition: hwdecoder.h:126
AVPacket * av_packet
FFmpeg internal data structure; encoded frame (say, H264)
Definition: hwdecoder.h:138
AVCodec * av_codec
FFmpeg internal data structure.
Definition: hwdecoder.h:140
AVBufferRef * hw_device_ctx
FFmpeg/libav hardware context.
Definition: hwdecoder.h:141
virtual ~AVHwDecoder()
Default destructor.
Definition: hwdecoder.cpp:145
AVCodecID av_codec_id
FFmpeg AVCodecId, identifying the codec.
Definition: hwdecoder.h:137
virtual void flush()
Reset decoder state. How to flush depends on the decoder library.
Definition: hwdecoder.cpp:162
AVCodecContext * av_codec_context
FFmpeg internal data structure.
Definition: hwdecoder.h:139
AVHwDecoder(AVCodecID av_codec_id, AVHWDeviceType hwtype, int n_threads=1)
Default constructor.
Definition: hwdecoder.cpp:52
virtual bool isOk()
The thread that uses this decoder can check if it has gone sour.
Definition: hwdecoder.cpp:167
A Virtual class for decoders.
Definition: decoder.h:62
Frame: An abstract queueable class.
Definition: frame.h:112
Definition: hwdecoder.h:153
HwVideoDecoder(AVCodecID av_codec_id, AVHWDeviceType hwtype, int n_threads=1)
Default constructor.
Definition: hwdecoder.cpp:172
virtual Frame * output()
Return a reference to the internal storage of the decoder where the decoded frame is.
Definition: hwdecoder.cpp:189
virtual ~HwVideoDecoder()
Default destructor.
Definition: hwdecoder.cpp:178
virtual bool pull()
Decode in_frame to out_frame. Return true if decoder returned a new frame (into out_frame),...
Definition: hwdecoder.cpp:194
FFmpeg decoders.