26#include <libavcodec/avcodec.h>
27#include <libavcodec/bsf.h>
29#include <libavutil/pixdesc.h>
32#include <vdr/thread.h>
54static enum AVPixelFormat
GetFormat(AVCodecContext * videoCtx,
55 const enum AVPixelFormat *fmt)
57 while (*fmt != AV_PIX_FMT_NONE) {
58 LOGDEBUG2(
L_CODEC,
"videocodec: %s: PixelFormat: %s videoCtx->pix_fmt: %s sw_pix_fmt: %s Codecname: %s",
60 av_get_pix_fmt_name(*fmt), av_get_pix_fmt_name(videoCtx->pix_fmt),
61 av_get_pix_fmt_name(videoCtx->sw_pix_fmt), videoCtx->codec->name);
62 if (*fmt == AV_PIX_FMT_DRM_PRIME) {
63 return AV_PIX_FMT_DRM_PRIME;
66 if (*fmt == AV_PIX_FMT_YUV420P) {
67 return AV_PIX_FMT_YUV420P;
71 LOGWARNING(
"videocodec: %s: No pixel format found! Set default format.", __FUNCTION__);
73 return avcodec_default_get_format(videoCtx, fmt);
85 const AVCodecHWConfig *config = NULL;
86 for (
int n = 0; (config = avcodec_get_hw_config(codec, n)); n++)
88 if (!(config->pix_fmt == AV_PIX_FMT_DRM_PRIME))
91 if ((config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) ||
92 (config->methods & AV_CODEC_HW_CONFIG_METHOD_INTERNAL))
109 const AVCodec *codec;
112 while ((codec = av_codec_iterate(&i))) {
113 if (!av_codec_is_decoder(codec))
115 if (codec->id != codecId)
136 return avcodec_find_decoder(codecId);
151 : m_identifier(identifier),
152 m_hardwareQuirks(hardwareQuirks)
156#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58,18,100)
157 avcodec_register_all();
175 AVRational timebase,
bool forceSoftwareDecoder,
176 int width,
int height)
184 const AVCodec *codec =
nullptr;
187 bool swCodecForced = forceSoftwareDecoder;
190 swCodecForced =
true;
193 avcodec_get_name(codecId), swCodecForced ?
" (sw decoding forced)" :
"");
200 LOGDEBUG2(
L_CODEC,
"videocodec: %s: no HW decoder found for codec \"%s\", try software decoder%s", __FUNCTION__, avcodec_get_name(codecId), swCodecForced ?
" (forced)" :
"");
207 LOGERROR(
"videocodec: %s: %s: Could not find any decoder for codec \"%s\"!",
m_identifier, __FUNCTION__, avcodec_get_name(codecId));
220 static AVBufferRef *hwDeviceCtx = NULL;
222 if (config && (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) {
223 const char *type_name = av_hwdevice_get_type_name(config->device_type);
224 if (av_hwdevice_ctx_create(&hwDeviceCtx, config->device_type, NULL, NULL, 0) < 0) {
227 type_name ? type_name :
"unknown");
236 if ((avcodec_parameters_to_context(
m_pVideoCtx, par)) < 0)
237 LOGERROR(
"videocodec: %s: %s: insert parameters to context failed!",
m_identifier, __FUNCTION__);
246 if (av_q2d(timebase) > 0)
249 if (codecId == AV_CODEC_ID_H264) {
256 }
else if (width && height) {
265 if (codec->capabilities & AV_CODEC_CAP_FRAME_THREADS ||
266 AV_CODEC_CAP_SLICE_THREADS) {
270 if (codec->capabilities & AV_CODEC_CAP_SLICE_THREADS)
288 LOGERROR(
"videocodec: %s: %s: Error opening the decoder: %s",
m_identifier, __FUNCTION__, av_err2str(err));
292 LOGDEBUG2(
L_CODEC,
"videocodec: %s: %s: Could not open hw decoder \"%s\", force using software decoder",
293 m_identifier, __FUNCTION__, codec->long_name ? codec->long_name : codec->name);
296 return Open(codecId, par, timebase,
true, 0, 0);
299 LOGINFO(
"videocodec: %s: %s (%s) for codec \"%s\" opened%s, using %s decoding with %d threads%s",
301 codec->long_name ? codec->long_name : codec->name,
303 avcodec_get_name(codecId),
304 swCodecForced ?
" (sw decoding forced)" :
"",
309 m_pCodecString = codec->long_name ? codec->long_name : codec->name;
343 AVBSFContext *bsfCtx;
344 const AVBitStreamFilter *f;
345 size_t extradataSize;
349 f = av_bsf_get_by_name(
"extract_extradata");
351 LOGERROR(
"videocodec: %s: %s: extradata av_bsf_get_by_name failed!",
m_identifier, __FUNCTION__);
355 ret = av_bsf_alloc(f, &bsfCtx);
363 ret = av_bsf_init(bsfCtx);
366 av_bsf_free(&bsfCtx);
370 AVPacket *dstPkt = av_packet_alloc();
371 AVPacket *pktRef = dstPkt;
375 av_bsf_free(&bsfCtx);
379 ret = av_packet_ref(pktRef, avpkt);
382 av_packet_free(&dstPkt);
383 av_bsf_free(&bsfCtx);
387 ret = av_bsf_send_packet(bsfCtx, pktRef);
389 LOGERROR(
"videocodec: %s: %s: extradata av_bsf_send_packet failed!",
m_identifier, __FUNCTION__);
390 av_packet_unref(pktRef);
391 av_packet_free(&dstPkt);
392 av_bsf_free(&bsfCtx);
396 ret = av_bsf_receive_packet(bsfCtx, pktRef);
398 LOGERROR(
"videocodec: %s: %s: extradata av_bsf_receive_packet failed!",
m_identifier, __FUNCTION__);
399 av_packet_unref(pktRef);
400 av_packet_free(&dstPkt);
401 av_bsf_free(&bsfCtx);
405 extradata = av_packet_get_side_data(pktRef, AV_PKT_DATA_NEW_EXTRADATA, &extradataSize);
407 m_pVideoCtx->extradata = (uint8_t *)av_mallocz(extradataSize + AV_INPUT_BUFFER_PADDING_SIZE);
408 memcpy(
m_pVideoCtx->extradata, extradata, extradataSize);
411 av_packet_unref(pktRef);
412 av_packet_free(&dstPkt);
413 av_bsf_free(&bsfCtx);
434 return AVERROR(EINVAL);
447 return AVERROR(EINVAL);
458 if (ret != AVERROR(EAGAIN))
490 return AVERROR(EINVAL);
493 if (!(pFrame = av_frame_alloc())) {
501 if (ret == AVERROR_EOF)
503 else if (ret != AVERROR(EAGAIN))
505 av_frame_free(&pFrame);
510 if (pFrame->flags == AV_FRAME_FLAG_CORRUPT)
525 av_frame_free(&pFrame);
527 return AVERROR(EAGAIN);
560 AVRational timebase,
int forceSoftwareDecoding)
594#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(58,7,100)
595 return frame->key_frame;
597 return frame->flags & AV_FRAME_FLAG_KEY;
static void LogFFmpegCallback(void *, int, const char *, va_list)
Callback for ffmpeg logs.
int ReopenCodec(enum AVCodecID, AVCodecParameters *, AVRational, int)
Reopen the video decoder.
int m_lastCodedHeight
save coded height while closing for a directly reopen
bool m_isHardwareDecoder
true, if this is a hardware decoder
int SendPacket(const AVPacket *)
Send a video packet to be decoded.
int Open(enum AVCodecID, AVCodecParameters *, AVRational, bool, int, int)
Open the video decoder.
int m_cntFramesReceived
number of decoded frames received from decoder
int GetExtraData(const AVPacket *)
Get extradata from avpkt.
int m_cntStartKeyFrames
number of keyframes arrived while starting the coded (needed for amlogic h264 decoder in order to dro...
void FlushBuffers(void)
Flush the video decoder.
cMutex m_mutex
mutex to lock codec context (TODO: is this needed?)
AVCodecContext * m_pVideoCtx
video codec context
int m_cntPacketsSent
number of packets sent to decoder
int m_lastCodedWidth
save coded width while closing for a directly reopen
const char * m_pCodecString
codec (long) name string
bool IsKeyFrame(AVFrame *)
Check, if this is a key frame.
const char * m_identifier
identifier for logging
int ReceiveFrame(AVFrame **)
Receive a decoded a video frame.
void Close(void)
Close video decoder.
int m_hardwareQuirks
hardware specific quirks needed for decoder
cVideoDecoder(int, const char *)
cVideoDecoder constructor
static const AVCodecHWConfig * FindHWConfig(const AVCodec *codec)
Find a hardware based video decoder config.
static enum AVPixelFormat GetFormat(AVCodecContext *videoCtx, const enum AVPixelFormat *fmt)
Callback to negotiate the PixelFormat.
static const AVCodec * FindHWDecoder(enum AVCodecID codecId)
Find a suitable video codec (hardware decoding)
static const AVCodec * FindSWDecoder(enum AVCodecID codecId)
Find a suitable video codec (software decoding)
Video decoder header file.
Logger class header file.
#define LOGFATAL
Logger macros.
Misc function header file.
static bool isInterlacedFrame(AVFrame *frame)
Check, if this is an interlaced frame.
static const char * Timestamp2String(int64_t ts, uint8_t divisor)
Workaround for av_err2str() not working with C++.
Videostream class header file.
#define QUIRK_CODEC_DISABLE_MPEG_HW
set, if disable mpeg hardware decoder
#define QUIRK_CODEC_DISABLE_H264_HW
set, if disable h264 hardware decoder
#define QUIRK_CODEC_SKIP_NUM_FRAMES
skip QUIRK_CODEC_SKIP_NUM_FRAMES, in case QUIRK_CODEC_SKIP_FIRST_FRAMES is set
#define QUIRK_CODEC_SKIP_FIRST_FRAMES
set, if codec should skip first I-Frames