29#include <libavcodec/avcodec.h>
30#include <libavfilter/buffersink.h>
31#include <libavfilter/buffersrc.h>
32#include <libavutil/opt.h>
36#include "vdr/thread.h"
60 LOGDEBUG(
"threads: decoding thread started");
70 LOGDEBUG(
"threads: decoding thread stopped");
78 LOGDEBUG(
"threads: stopping decoding thread");
99 LOGDEBUG(
"threads: display thread started");
109 if (scheduleImmediately)
114 LOGDEBUG(
"threads: display thread stopped");
122 LOGDEBUG(
"threads: stopping display thread");
143 LOGDEBUG(
"threads: audio thread started");
150 LOGDEBUG(
"threads: audio thread stopped");
158 LOGDEBUG(
"threads: stopping audio thread");
189 const char *filterDescr = NULL;
192 LOGFATAL(
"filter thread: %s: Cannot alloc filter graph", __FUNCTION__);
197 const AVFilter *buffersrc = avfilter_get_by_name(
"buffer");
198 const AVFilter *buffersink = avfilter_get_by_name(
"buffersink");
204 if (enableDeinterlacer) {
205 if (frame->format == AV_PIX_FMT_DRM_PRIME) {
206 filterDescr =
"deinterlace_v4l2m2m";
207 }
else if (frame->format == AV_PIX_FMT_YUV420P) {
208 filterDescr =
"bwdif=1:-1:0";
211 }
else if (frame->format == AV_PIX_FMT_YUV420P) {
212 filterDescr =
"scale";
214 LOGFATAL(
"filter thread: %s: Unexpected pixel format: %d", __FUNCTION__, frame->format);
215#if LIBAVFILTER_VERSION_INT < AV_VERSION_INT(7,16,100)
216 avfilter_register_all();
221 int sarNum = videoCtx->sample_aspect_ratio.num != 0 ? videoCtx->sample_aspect_ratio.num : (videoCtx->height == 576 ? 64 : 1);
222 int sarDen = videoCtx->sample_aspect_ratio.num != 0 ? videoCtx->sample_aspect_ratio.den : (videoCtx->height == 576 ? 45 : 1);
224 snprintf(args,
sizeof(args),
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
225 videoCtx->width, videoCtx->height, frame->format,
226 videoCtx->pkt_timebase.num ? videoCtx->pkt_timebase.num : 1,
227 videoCtx->pkt_timebase.num ? videoCtx->pkt_timebase.den : 1,
231 LOGDEBUG2(
L_CODEC,
"filter thread: %s: filter=\"%s\" args=\"%s\"", __FUNCTION__, filterDescr, args);
235 LOGFATAL(
"filter thread: %s: Cannot create buffer source (%d)", __FUNCTION__, ret);
237 AVBufferSrcParameters *par = av_buffersrc_parameters_alloc();
238 memset(par, 0,
sizeof(*par));
239 par->format = AV_PIX_FMT_NONE;
240 par->hw_frames_ctx = frame->hw_frames_ctx;
243 LOGFATAL(
"filter thread: %s: Cannot av_buffersrc_parameters_set (%d)", __FUNCTION__, ret);
249 LOGFATAL(
"filter thread: %s: Cannot create buffer sink (%d)", __FUNCTION__, ret);
251 if (frame->format != AV_PIX_FMT_DRM_PRIME) {
252 enum AVPixelFormat pixFmts[] = { AV_PIX_FMT_NV12, AV_PIX_FMT_NONE };
253 ret = av_opt_set_int_list(
m_pBuffersinkCtx,
"pix_fmts", pixFmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
255 LOGFATAL(
"filter thread: %s: Cannot set output pixel format (%d)", __FUNCTION__, ret);
258 AVFilterInOut *outputs = avfilter_inout_alloc();
259 AVFilterInOut *inputs = avfilter_inout_alloc();
261 outputs->name = av_strdup(
"in");
263 outputs->pad_idx = 0;
264 outputs->next = NULL;
266 inputs->name = av_strdup(
"out");
271 ret = avfilter_graph_parse_ptr(
m_pFilterGraph, filterDescr, &inputs, &outputs, NULL);
272 avfilter_inout_free(&inputs);
273 avfilter_inout_free(&outputs);
276 LOGFATAL(
"filter thread: %s: avfilter_graph_parse_ptr failed (%d)", __FUNCTION__, ret);
281 LOGFATAL(
"filter thread: %s: avfilter_graph_config failed (%d)", __FUNCTION__, ret);
288 LOGDEBUG(
"threads: video filter thread started");
304 if ((ret = av_buffersrc_add_frame_flags(
m_pBuffersrcCtx, frame, AV_BUFFERSRC_FLAG_KEEP_REF)) < 0)
305 LOGWARNING(
"filter thread: %s: can't add_frame: %s", __FUNCTION__, av_err2str(ret));
307 av_frame_free(&frame);
311 AVFrame *filtFrame = av_frame_alloc();
313 LOGFATAL(
"filter thread: %s: can't allocate frame", __FUNCTION__);
317 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
318 av_frame_free(&filtFrame);
320 }
else if (ret < 0) {
321 LOGERROR(
"filter thread: %s: can't get filtered frame: %s", __FUNCTION__, av_err2str(ret));
322 av_frame_free(&filtFrame);
330 if (filtFrame->format == AV_PIX_FMT_NV12 &&
m_filterBug)
335 av_frame_free(&filtFrame);
338 LOGDEBUG(
"threads: filter thread stopped");
354 LOGDEBUG(
"threads: stopping filter thread");
361 av_frame_free(&frame);
Audio and alsa module header file.
cAudioThread(cSoftHdAudio *)
virtual ~cAudioThread(void)
virtual void Action(void)
cDecodingThread(cVideoStream *, const char *)
virtual void Action(void)
virtual ~cDecodingThread(void)
cDisplayThread(cVideoRender *)
virtual void Action(void)
virtual ~cDisplayThread(void)
void InitAndStart(const AVCodecContext *, AVFrame *, bool)
Init and start the video filter thread.
AVFilterContext * m_pBuffersinkCtx
void PushFrame(AVFrame *)
Put a frame in the buffer to be filtered.
cQueue< cDrmBuffer > * m_pDrmBufferQueue
pointer to renderer's DRM buffer queue
AVFilterContext * m_pBuffersrcCtx
bool m_filterBug
flag for a ffmpeg bug
AVFilterGraph * m_pFilterGraph
cFilterThread(cVideoRender *, cQueue< cDrmBuffer > *, const char *, std::function< void(AVFrame *)>)
int m_numFramesToFilter
number of frames to be filtered
std::function< void(AVFrame *)> m_frameOutput
function to output the frame
virtual ~cFilterThread(void)
cQueue< AVFrame > m_frames
queue for frames to be filtered
T * Pop(void)
Pop an element from the back of the queue.
bool IsEmpty(void)
Check if the queue is empty.
bool IsFull(void)
Check if the queue is full.
bool Push(T *element)
Push an element to the front of the queue.
cSoftHdAudio - Audio class
void ProcessEvents(void)
Process queued events and forward to event receiver.
bool CyclicCall(void)
Cyclic audio playback call.
cVideoRender - Video render class
void ProcessEvents(void)
Process queued events and forward to event receiver.
bool DisplayFrame()
Display the frame (video and/or osd)
cVideoStream - Video stream class
void DecodeInput(void)
Decodes a reassembled codec packet.
Logger class header file.
#define LOGFATAL
Logger macros.
Misc function header file.
static bool isInterlacedFrame(AVFrame *frame)
Check, if this is an interlaced frame.
Thread classes header file.
Rendering class header file.
Videostream class header file.