vdr-plugin-softhddevice-drm-gles 1.6.8-daba64b
videostream.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: AGPL-3.0-or-later
2
17#include <functional>
18#include <set>
19#include <string>
20#include <vector>
21
22extern "C" {
23#include <libavcodec/avcodec.h>
24#include <libavformat/avformat.h>
25#include <libavutil/timestamp.h>
26}
27
28#include <vdr/thread.h>
29
30#include "codec_video.h"
31#include "config.h"
32#include "h264parser.h"
33#include "hardwaredevice.h"
34#include "logger.h"
35#include "misc.h"
36#include "queue.h"
37#include "videofilter.h"
38#include "videostream.h"
39#include "videorender.h"
40
41/*****************************************************************************
42 * cVideoStream class
43 ****************************************************************************/
44
49 : cThread(isPipStream ? "shd PIP decode" : "shd main decode"),
50 m_pConfig(config),
51 m_pDecoder(nullptr),
52 m_pRender(render),
53 m_identifier(isPipStream ? "PIP" : "main"),
54 m_frameOutput(frameOutput),
55 m_pDrmBufferQueue(drmBufferQueue),
56 m_videoFilter(render, m_pDrmBufferQueue, isPipStream ? "shd PIP filter" : "shd main filter", frameOutput),
57 m_hardwareQuirks(hardwareQuirks),
58 m_userDisabledDeinterlacer(config->ConfigDisableDeint),
59 m_deinterlacerDeactivated(isPipStream ? true : false),
60 m_startDecodingWithIFrame(config->ConfigDecoderNeedsIFrame),
61 m_parseH264Dimensions(config->ConfigParseH264Dimensions)
62{
64
65 LOGDEBUG("videostream %s: %s", __FUNCTION__, m_identifier);
67 LOGDEBUG2(L_CODEC, "videostream %s: %s: fallback to sw decoder after %d packets sent", __FUNCTION__, m_identifier, m_decoderFallbackToSwNumPkts);
68}
69
71{
72 LOGDEBUG("videostream %s: %s", __FUNCTION__, m_identifier);
73}
74
82{
83 m_packets.Push(nullptr);
84}
85
97{
98 if (avpkt->pts != AV_NOPTS_VALUE)
99 m_inputPts = avpkt->pts;
100
101 LOGDEBUG2(L_PACKET, "videostream: %s: push PTS %s", __FUNCTION__, Timestamp2String(avpkt->pts, 90));
102
103 return m_packets.Push(avpkt);
104}
105
110{
111 LOGDEBUG("videostream %s: %s:", m_identifier, __FUNCTION__);
112
113 Stop();
114
115 if (m_pDecoder) {
116 m_pDecoder->Close();
117 delete(m_pDecoder);
118 m_pDecoder = nullptr;
119 }
120
122}
123
128{
129 LOGDEBUG("videostream %s: %s: packets %d", m_identifier, __FUNCTION__, m_packets.Size());
130
131 while (!m_packets.IsEmpty()) {
134 }
135
137}
138
152
157{
158 LOGDEBUG2(L_CODEC, "videostream %s: %s", m_identifier, __FUNCTION__);
159
161 m_pDecoder->Close();
162 m_pPar = nullptr;
163 m_numIFrames = 0;
164 m_maxFrameNum = 1;
165 m_naluTypesAtStart.clear();
166 m_dpbFrames.clear();
169 m_framerate = 0.0;
170}
171
179{
180 LOGDEBUG2(L_CODEC, "videostream %s: %s", m_identifier, __FUNCTION__);
182
185 LOGFATAL("videostream %s: %s: Could not reopen the decoder (flush)!", m_identifier, __FUNCTION__);
186 } else {
188 }
189}
190
204{
205 int minPkts = m_interlaced ? m_trickpkts : 1;
206
209 if (m_sentTrickPkts >= minPkts) {
211 m_sentTrickPkts = 0;
212 }
213 }
214}
215
220{
221 int width = 0;
222 int height = 0;
223
227
233 if (!h264Packet.HasSPS()) {
234 LOGDEBUG2(L_CODEC, "videostream %s: %s: No SPS in the packet!", m_identifier, __FUNCTION__);
235 h264Packet.PrintStreamData();
236 }
237
238 // start decoding with an I-Frame only
239 if (!h264Packet.IsISlice() && m_startDecodingWithIFrame) {
240 h264Packet.PrintNalUnits();
241 LOGDEBUG2(L_CODEC, "videostream %s: %s: Skip h264 packet, no I-Frame!", m_identifier, __FUNCTION__);
244 return;
245 }
246
247 // amlogic h264 decoder needs width an height for correct decoder open
249 width = h264Packet.GetWidth();
250 height = h264Packet.GetHeight();
251 LOGDEBUG2(L_CODEC, "videostream %s: %s: Parsed width %d height %d", m_identifier, __FUNCTION__, width, height);
252 }
253 }
254
255 if (m_pDecoder->Open(m_codecId, m_pPar, m_timebase, false, width, height))
256 LOGFATAL("videostream %s: %s: Could not open the decoder!", m_identifier, __FUNCTION__);
257
258 m_pConfig->CurrentDecoderType = m_pDecoder->IsHardwareDecoder() ? "hardware" : "software";
260 m_newStream = false;
263}
264
278{
283
284 if (h264Packet.HasSPS()) {
285 m_maxFrameNum = 1 << (h264Packet.GetLog2MaxFrameNumMinus4() + 4);
286 m_log2MaxFrameNumMinus4 = h264Packet.GetLog2MaxFrameNumMinus4();
287 }
288
289 if (h264Packet.HasPPS()) {
290 m_ppsNumRefIdxL0DefaultActiveMinus1 = h264Packet.GetPpsNumRefIdxL0DefaultActiveMinus1();
291 m_ppsNumRefIdxL1DefaultActiveMinus1 = h264Packet.GetPpsNumRefIdxL1DefaultActiveMinus1();
292 }
293
294 int frameNumber = h264Packet.GetFrameNum();
295
296 if (h264Packet.IsReference()) {
297 h264Packet.AddFrameNumber(frameNumber);
298 m_dpbFrames.insert(frameNumber);
299 } else {
300 h264Packet.AddFrameNumber(-1);
301 }
302
303 if (h264Packet.IsISlice())
304 m_numIFrames++;
305
306 m_naluTypesAtStart.push_back(h264Packet.GetNalUnitString());
307
308 if (h264Packet.IsPSlice() || h264Packet.IsBSlice()) {
309 int numRefL0 = h264Packet.GetNumRefIdxL0Active();
310 int numRefL1 = h264Packet.GetNumRefIdxL1Active();
311
312 for (auto& mod : h264Packet.GetRefMods()) {
313 if (mod.idc != 0 && mod.idc != 1)
314 continue;
315
316 int activeRefs = (mod.list == 0) ? numRefL0 : numRefL1;
317 if (activeRefs <= 0)
318 continue;
319
320 // Compute the short-term reference frame number
321 int modRef = -1;
322 int diff = mod.abs_diff_pic_num_minus1 + 1;
323
324 if (mod.idc == 0) { // subtraction
326 } else if (mod.idc == 1) { // addition
328 }
329
330 // Check if this reference exists in the DPB
331 if (m_dpbFrames.find(modRef) == m_dpbFrames.end()) {
332 h264Packet.AddInvalidReference(modRef, frameNumber);
333 } else {
334 h264Packet.AddValidReference(modRef);
335 }
336 }
337
338 // only print invalid references for better readability
339 h264Packet.BuildInvalidReferenceString(frameNumber);
340 // h264Packet.BuildValidReferenceString();
341
342 if (h264Packet.HasInvalidBackwardReferences() && h264Packet.IsPSlice() && m_numIFrames - 1 < m_dropInvalidPackets) {
343 LOGDEBUG2(L_CODEC, "videostream %s: %s: invalid backward reference, drop P-Frame %d", m_identifier, __FUNCTION__, frameNumber);
344 return true;
345 }
346 }
347
348 return false;
349}
350
358{
360 return false;
361
362 // Check, if the packet should be dropped
364 return ParseH264Packet(avpkt);
365
366 // otherwise just log H.264 frames up to the given number of I-Frames
367 if (m_logPackets) {
368 LOGDEBUG("videostream %s: %s: parsed H.264 stream:", m_identifier, __FUNCTION__);
369 for (std::size_t i = 0; i < m_naluTypesAtStart.size(); i++)
370 LOGDEBUG("[H264] (%02d) %s", i, m_naluTypesAtStart[i].c_str());
371
372 m_logPackets = 0;
373 }
374
375 return false;
376}
377
382{
383 AVFrame *frame = nullptr;
384 int ret = 0;
385
387 return;
388
389 if (m_newStream)
390 OpenDecoder();
391
392 // caution: avpkt can be a nullptr from cVideoStream::Flush(), we may not dereference it later without nullptr-check!
394
395 // Force a decoder drain if the new pts is more than AV_SYNC_BORDER_MS
396 // greater than the last one.
397 // VDR may deliver packets out of pts order around the 33-bit PTS wrap.
398 // In that case a numerically larger PTS may actually belong to an older
399 // frame. Ignore differences greater than half the PTS range so they are
400 // not mistaken for discontinuities.
403 std::abs(PtsToMs(avpkt->pts) - PtsToMs(m_lastDecodedPts)) < PtsToMs(1LL << 32)) {
404
405 LOGDEBUG2(L_CODEC, "videostream: %s: discontinuity detected in video PTS %s -> %s, force decoder flush", __FUNCTION__,
407
409 m_lastDecodedPts = avpkt->pts;
410
411 // send packet to decoder
412 } else if (!PacketDropNeeded(avpkt)) {
414 m_isResend = false;
415
416 if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
417 avpkt = m_packets.Pop();
418 if (avpkt && avpkt->pts != AV_NOPTS_VALUE)
419 m_lastDecodedPts = avpkt->pts;
421 // a repeated decoder drain was requested, drop the nullptr-packet from the queue
422 } else if (ret == AVERROR_EOF && !avpkt) {
423 m_packets.Pop();
424 } else {
425 // PacketDropNeeded() is skipped next time, because this packet needs to be resent to the decoder
426 m_isResend = true;
427 }
428
429 if (!ret && m_pRender->IsTrickSpeed())
431
432 // drop packet
433 } else {
434 avpkt = m_packets.Pop();
436 m_isResend = false;
437 }
438
439 // receive frame from decoder
440 ret = m_pDecoder->ReceiveFrame(&frame);
441 if (ret == 0) {
442 RenderFrame(frame);
443 } else if (ret == AVERROR_EOF) {
444 FlushDecoder();
445 m_sentTrickPkts = 0;
446 }
447
449 // log maximum number of packets needed for the hw decoder to deliver a frame
452
453 // fallback to software decoder if configured and hw decoder fails
455 LOGWARNING("videostream %s: %s: Could not decode frame after %d packets sent, fallback to software decoder!", m_identifier, __FUNCTION__, m_decoderFallbackToSwNumPkts);
457 LOGFATAL("videostream %s: %s: Could not reopen the decoder (sw fallback)!", m_identifier, __FUNCTION__);
458 }
459 }
460}
461
469void cVideoStream::GetVideoSize(int *width, int *height, double *aspect_ratio)
470{
472
473 if (m_pDecoder && videoCtx) {
474 *width = videoCtx->coded_width;
475 *height = videoCtx->coded_height;
476 *aspect_ratio = *width / (double)*height;
477 } else {
478 *width = 0;
479 *height = 0;
480 *aspect_ratio = 1.0;
481 }
482}
483
492 m_newStream = true;
493 m_trickpkts = codecId == AV_CODEC_ID_MPEG2VIDEO ? 1 : 2;
495 m_codecId = codecId;
496 m_pPar = par;
497}
498
499/*****************************************************************************
500 * Thread
501 ****************************************************************************/
502
507{
508 LOGDEBUG("videostream: decoding thread started");
509 while(Running()) {
510 m_mutex.lock();
511
512 DecodeInput();
513
514 m_mutex.unlock();
515
516 usleep(1000);
517 }
518 LOGDEBUG("videostream: decoding thread stopped");
519}
520
525{
526 if (!Active())
527 return;
528
529 LOGDEBUG("videostream: stopping decoding thread");
530 Cancel(2);
531}
532
537 if (m_videoFilter.Active())
539
541 m_useDeinterlacer = false;
543}
544
554{
555 if (frame->decode_error_flags || frame->flags & AV_FRAME_FLAG_CORRUPT)
556 LOGWARNING("videostream: %s: %s: error_flag or FRAME_FLAG_CORRUPT", m_identifier, __FUNCTION__);
557
558 if (!m_framerate) {
559 if (av_q2d(m_pDecoder->GetContext()->framerate) > 0.0) {
560 // the decoder has a valid framerate, use it
561 m_framerate = av_q2d(m_pDecoder->GetContext()->framerate);
562 } else if (frame->pts != AV_NOPTS_VALUE) {
563 // The decoder has no valid framerate, calculate it from pts and timebase
564 // @todo We are only using the first two frames here.
565 // If there are issues in the stream this might not be correct.
568 m_framerate = 1.0 / (delta * av_q2d(m_timebase));
569 }
570 m_ptsForFramerateDetection = frame->pts;
571 }
572 }
573
574 // Filter thread will only be started, if the lambda function returns true
576 m_timebase = m_pDecoder->GetContext()->pkt_timebase;
577
578 // Enable the deinterlacer only if:
579 // --------------------------------
580 // - The user did not disable the deinterlacer
581 // - The deinterlacer is not temporarily deactivated (trickspeed and still picture)
582 // - A hardware quirk does not forbid using the deinterlacer
583 // - It is an interlaced stream, determined by:
584 // - The codec is different from HEVC (always progressive)
585 // - The framerate is lower or equal to 30fps
586 // - Or, if the frame's interlaced flag is set
587 // - the display cannot handle an interlaced mode
588 // - the display can handle an interlaced mode, but the user doesn't want to use it
589 //
590 // General interlaced stream detection:
591 // ------------------------------------
592 // We cannot solely rely on the frame's interlaced flag, because the deinterlacer shall also be enabled with mixed progressive/interlaced streams (e.g. TV station "ProSieben").
593
595 (m_pDecoder->GetContext()->codec_id != AV_CODEC_ID_HEVC &&
596 m_pDecoder->GetContext()->framerate.num > 0 &&
597 av_q2d(m_pDecoder->GetContext()->framerate) < 30.1) || isInterlacedFrame(frame); // account for rounding errors when comparing double
598
599 // don't use the deinterlacer, if display mode should follow video including interlacing
601
602 // test, if display can handle the requested mode
603 // if the interlaced stream should be deinterlaced, the new mode will have doubled framerate and is progressive
604 sDrmMode mode = { m_pDecoder->GetContext()->coded_width,
605 m_pDecoder->GetContext()->coded_height,
609
611 m_interlaced &&
616
618 LOGDEBUG("videostream: %s: %s: deinterlacer disabled by user configuration", m_identifier, __FUNCTION__);
619
620 // Use the filter thread if:
621 // - AV_PIX_FMT_YUV420P, interlaced -> software deinterlacer (bwdif filter)
622 // - AV_PIX_FMT_YUV420P, progressive -> scale filter to get NV12 frames
623 // - AV_PIX_FMT_DRM_PRIME, interlaced, hw deinterlacer available -> hw deinterlacer
624 if (frame->format == AV_PIX_FMT_YUV420P || (frame->format == AV_PIX_FMT_DRM_PRIME && m_useDeinterlacer))
626
628 }
629
630 // if interlaced material was forced to be deinterlaced, we have doubled framerate and progressive mode now
633
634 // reset the display mode if needed
635 if (m_framerate &&
640
642 m_pDecoder->GetContext()->coded_height,
645
647 }
648
649 if (m_videoFilter.Active())
651 else {
652 // AV_PIX_FMT_DRM_PRIME, interlaced, hw deinterlacer not available
653 // AV_PIX_FMT_DRM_PRIME, progressive
654 // -> put the frame directly into render buffer
656 m_frameOutput(frame);
657 }
658}
659
H.264 Parser.
Definition h264parser.h:45
T * Pop(void)
Pop an element from the back of the queue.
Definition queue.h:57
bool IsEmpty(void)
Check if the queue is empty.
Definition queue.h:99
bool IsFull(void)
Check if the queue is full.
Definition queue.h:110
bool Push(T *element)
Push an element to the front of the queue.
Definition queue.h:40
size_t Size(void)
Get the current size of the queue.
Definition queue.h:121
T * Peek(void)
Get a reference to the back element.
Definition queue.h:75
Plugin Configuration.
Definition config.h:65
int ConfigVideoDisplayMode
display mode (enum ConfigDisplayModes)
Definition config.h:76
int ConfigParseH264StreamStart
log frames at stream start up to the given number of I-Frames
Definition config.h:120
int ConfigDecoderFallbackToSwNumPkts
maximum number of packets sent before fallback to sw decoder
Definition config.h:117
void SetDecoderNeedsMaxPackets(int)
Definition config.cpp:151
const char * CurrentDecoderType
current decoder type: "hardware" or "software"
Definition config.h:144
const char * CurrentDecoderName
current decoder name
Definition config.h:143
bool ConfigDecoderFallbackToSw
fallback to software decoder if the hardware decoder fails
Definition config.h:116
int GetDecoderNeedsMaxPackets(void)
Definition config.cpp:157
sDrmMode CurrentVideoDrmMode
currently used video drm mode
Definition config.h:153
int ConfigDropInvalidH264PFrames
drop P-Frames with invalid references on stream start up to the given number of I-Frames
Definition config.h:121
Video Decoder.
Definition codec_video.h:37
int ReopenCodec(enum AVCodecID, AVCodecParameters *, AVRational, int)
Reopen the video decoder.
AVCodecContext * GetContext(void)
Definition codec_video.h:46
int SendPacket(const AVPacket *)
Send a video packet to be decoded.
int Open(enum AVCodecID, AVCodecParameters *, AVRational, bool, int, int)
Open the video decoder.
void SetSkipKeyFramesNum(int num)
Definition codec_video.h:51
bool IsHardwareDecoder(void)
Definition codec_video.h:47
int GetFramesReceived(void)
Definition codec_video.h:50
void FlushBuffers(void)
Flush the video decoder buffers.
int ReceiveFrame(AVFrame **)
Receive a decoded a video frame.
int GetPacketsSent(void)
Definition codec_video.h:49
const char * Name(void)
Definition codec_video.h:48
void Close(void)
Close video decoder.
int GetNumFramesToFilter(void)
Definition videofilter.h:49
bool IsInputBufferEmpty(void)
Definition videofilter.h:48
void InitAndStart(const AVCodecContext *, AVFrame *, bool)
Init and start the video filter thread.
void Stop(void)
Stops the filter thread and does a cleanup.
bool IsInputBufferFull(void)
Definition videofilter.h:47
void PushFrame(AVFrame *)
Puts a frame in the buffer to be filtered.
Video Renderer.
void SetDisplayMode(int)
Wrapper to set the display mode.
bool IsForwardTrickspeed(void)
bool IsTrickSpeed(void)
bool PresentationPending(void)
bool CanHandleMode(sDrmMode *)
Wrapper to check, if drm can handle the display mode.
std::mutex m_mutex
mutex for decoding thread control
bool m_interlaced
flag for interlaced stream
void GetVideoSize(int *, int *, double *)
Get video size and aspect ratio.
bool BuffersEmpty(void)
Return true, if the input AVPacket, videofilter and drm output buffer queues are empty.
bool ParseH264Packet(AVPacket *)
Parse an H.264 packet and test, if the packet is a P-Slice with invalid backward references.
void OpenDecoder(void)
Open the decoder including an H.264 parsing if needed.
int m_dropInvalidPackets
drop P-Frames with invalid references until the given number of I-Frames arrived
std::function< void(AVFrame *)> m_frameOutput
function to output the frame
const char * m_identifier
identifier string for logging
cSoftHdConfig * m_pConfig
plugin config
Definition videostream.h:97
int64_t m_inputPts
PTS of the first packet in the input buffer.
double m_framerate
current stream framerate
bool m_deinterlacerDeactivated
set, if the deinterlacer should be disabled temporarily (trickspeed, stillpicture,...
int m_sentTrickPkts
how many avpkt have been sent to the decoder in trickspeed mode?
int m_logPackets
parse and log all frames until the number of given I-Frames arrived
bool m_parseH264Dimensions
parse width and height when starting an h264 stream
void StartDecoder()
Start the decoder.
void CheckForcingFrameDecode(void)
Check, if we need to force the decoder to decode the frame (force a decoder drain)
bool m_startDecodingWithIFrame
wait for an I-Frame to start h264 decoding
void ClearVdrCoreToDecoderQueue(void)
Clears all video stream data, which is buffered to be decoded.
bool m_userDisabledDeinterlacer
set, if the user configured the deinterlace to be disabled
volatile bool m_newStream
flag for new stream
int m_ppsNumRefIdxL1DefaultActiveMinus1
cache NumRefIdxL1DefaultActiveMinuns1 from a previous PPS parsing
enum AVCodecID m_codecId
current codec id
bool m_checkFilterThreadNeeded
set, if we have to check, if filter thread is needed at start of playback
int64_t m_ptsForFramerateDetection
helper PTS to calculate a framerate at stream start
bool m_useDeinterlacer
set, if the deinterlacer is used
int m_log2MaxFrameNumMinus4
cache Log2MaxFrameNumMinus4 from a previous SPS parsing
AVCodecParameters * m_pPar
current codec parameters
int m_decoderFallbackToSwNumPkts
fallback to sw decoder if hw decoder fails after the given number of packets sent
void DecodeInput(void)
Decodes a reassembled codec packet.
bool m_isResend
track, if we already tried to send the AVPacket to the decoder if so, skip the parsing
void Stop(void)
Stop the decoding thread.
static constexpr int AV_SYNC_BORDER_MS
absolute max a/v difference which should trigger a decoder flush
cQueue< cDrmBuffer > * m_pDrmBufferQueue
pointer to renderer's DRM buffer queue
void Drain(void)
Drains the video stream by finalizing any pending data.
virtual void Action(void)
Decoding thread loop, which periodically tries to decode input.
void CloseDecoder(void)
Close the decoder.
int m_hardwareQuirks
hardware specific quirks
cVideoDecoder * m_pDecoder
video decoder
Definition videostream.h:98
cVideoFilter m_videoFilter
pointer to deinterlace/scaling video filter thread
int m_maxFrameNum
= 1 << Log2MaxFrameNumMinus4 + 4
void Exit(void)
Exit video stream.
cVideoStream(cVideoRender *, int, cQueue< cDrmBuffer > *, cSoftHdConfig *, bool, std::function< void(AVFrame *)>)
Create a video stream.
virtual ~cVideoStream(void)
std::vector< std::string > m_naluTypesAtStart
array of strings to log the H.264 frames at stream start
void CancelFilterThread(void)
Stop filter thread.
int m_ppsNumRefIdxL0DefaultActiveMinus1
cache NumRefIdxL0DefaultActiveMinuns1 from a previous PPS parsing
cVideoRender * m_pRender
video renderer
Definition videostream.h:99
int m_trickpkts
how many avpkt does the decoder need in trickspeed mode?
void RenderFrame(AVFrame *)
Render a frame.
cQueue< AVPacket > m_packets
AVPackets queue.
int64_t m_lastDecodedPts
PTS of the latest packet, which was sent to the decoder in order to detect stream discontinuity.
void FlushDecoder(void)
Flush the decoder.
void Open(AVCodecID, AVCodecParameters *=nullptr, AVRational={ .num=1,.den=90000 })
Open a video codec.
bool PushAvPacket(AVPacket *avpkt)
Pushes a pre-assembled AVPacket directly to the processing queue.
bool PacketDropNeeded(AVPacket *)
Test if the packet should be dropped and parse it if needed (see cVideoStream::ParseH264())
virtual void SetDeinterlacerDeactivated(bool deactivate)
Definition videostream.h:85
int64_t PtsToMs(int64_t pts)
int m_numIFrames
counter for the arriving I-Frames at H.264 stream start
std::atomic< struct AVRational > m_timebase
current codec timebase
std::set< int > m_dpbFrames
private set of reference frames (internal short-time decoded picture buffer)
Video Decoder Header File.
Plugin Configuration Header File.
@ CONFIG_DISPLAY_MODE_FOLLOW_VIDEO_INTERLACED
Definition config.h:45
#define LOGDEBUG2
log to LOG_DEBUG and add a prefix
Definition logger.h:47
#define LOGDEBUG
log to LOG_DEBUG
Definition logger.h:45
#define AV_NOPTS_VALUE
Definition misc.h:74
#define LOGWARNING
log to LOG_WARN
Definition logger.h:41
#define LOGFATAL
log to LOG_ERR and abort
Definition logger.h:37
static bool isInterlacedFrame(AVFrame *frame)
Check, if this is an interlaced frame.
Definition misc.h:86
static const char * Timestamp2String(int64_t ts, uint8_t divisor)
Nice time-stamp string.
Definition misc.h:127
@ QUIRK_CODEC_FLUSH_WORKAROUND
set, if we have to close and reopen the codec instead of avcodec_flush_buffers (rpi)
@ QUIRK_CODEC_SKIP_FIRST_FRAMES
set, if codec should skip first I-Frames
@ QUIRK_CODEC_SKIP_NUM_FRAMES
skip QUIRK_CODEC_SKIP_NUM_FRAMES, in case QUIRK_CODEC_SKIP_FIRST_FRAMES is set
@ QUIRK_CODEC_NEEDS_DIMENSION_PARSE
set, if codec needs some infos for init (coded_width and coded_height)
@ QUIRK_NO_HW_DEINT
set, if no hw deinterlacer available
@ L_PACKET
decoder packet/frame tracking logs
Definition logger.h:68
@ L_CODEC
codec logs
Definition logger.h:61
H.264 Parser Header File.
Describes a hardware device.
Logger Header File.
Misc Functions.
Thread-safe Queue.
Holds possible display configurations.
Definition config.h:30
int width
display width
Definition config.h:31
bool interlaced
is this an interlaced mode?
Definition config.h:34
int height
display height
Definition config.h:32
double refreshRateHz
display refresh rate
Definition config.h:33
Deinterlace and Scaling Filters Header File.
Video Renderer (Display) Header File.
Video Input Stream Header File.