1 diff -ur tvheadend-4.0.8.orig/configure tvheadend-4.0.8/configure
2 --- tvheadend-4.0.8.orig/configure 2015-12-16 18:33:33.000000000 +0100
3 +++ tvheadend-4.0.8/configure 2016-04-16 19:41:41.685840403 +0200
8 - if $has_libav && ! check_pkg libswscale ">=2.3.100"; then
9 + if $has_libav && ! check_pkg libavfilter ">=4.0.0"; then
17 - if $has_libav && ! check_pkg libswscale ">=2.1.2"; then
18 + if $has_libav && ! check_pkg libavfilter ">=4.0.0"; then
22 diff -ur tvheadend-4.0.8.orig/Makefile tvheadend-4.0.8/Makefile
23 --- tvheadend-4.0.8.orig/Makefile 2015-12-16 18:33:33.000000000 +0100
24 +++ tvheadend-4.0.8/Makefile 2016-04-16 19:41:41.685840403 +0200
26 LDFLAGS_FFDIR = ${ROOTDIR}/libav_static/build/ffmpeg/lib
27 LDFLAGS += ${LDFLAGS_FFDIR}/libavresample.a
28 LDFLAGS += ${LDFLAGS_FFDIR}/libswresample.a
29 -LDFLAGS += ${LDFLAGS_FFDIR}/libswscale.a
30 +LDFLAGS += ${LDFLAGS_FFDIR}/libavfilter.a
31 LDFLAGS += ${LDFLAGS_FFDIR}/libavutil.a
32 LDFLAGS += ${LDFLAGS_FFDIR}/libavformat.a
33 LDFLAGS += ${LDFLAGS_FFDIR}/libavcodec.a
34 diff -ur tvheadend-4.0.8.orig/Makefile.ffmpeg tvheadend-4.0.8/Makefile.ffmpeg
35 --- tvheadend-4.0.8.orig/Makefile.ffmpeg 2015-12-16 18:33:33.000000000 +0100
36 +++ tvheadend-4.0.8/Makefile.ffmpeg 2016-04-16 19:41:41.685840403 +0200
38 FFMPEG_SHA1 = 65470c9b967485f72f81758a7bad44cf7a1763db
40 EXTLIBS = libx264 libvorbis libvpx
41 -COMPONENTS = avutil avformat avcodec swresample swscale avresample
42 +COMPONENTS = avutil avformat avcodec swresample avfilter avresample
44 DECODERS = mpeg2video mp2 ac3 eac3 h264 h264_vdpau aac aac_latm vorbis libvorbis
45 ENCODERS = mpeg2video mp2 libx264 libvpx_vp8 libvpx_vp9 aac libaacplus vorbis libvorbis
46 diff -ur tvheadend-4.0.8.orig/src/libav.c tvheadend-4.0.8/src/libav.c
47 --- tvheadend-4.0.8.orig/src/libav.c 2015-12-16 18:33:33.000000000 +0100
48 +++ tvheadend-4.0.8/src/libav.c 2016-04-16 19:44:03.666521276 +0200
50 av_log_set_callback(libav_log_callback);
51 av_log_set_level(AV_LOG_VERBOSE);
53 + avfilter_register_all();
55 diff -ur tvheadend-4.0.8.orig/src/libav.h tvheadend-4.0.8/src/libav.h
56 --- tvheadend-4.0.8.orig/src/libav.h 2015-12-16 18:33:33.000000000 +0100
57 +++ tvheadend-4.0.8/src/libav.h 2016-04-16 19:41:41.685840403 +0200
61 #include <libavformat/avformat.h>
62 +#include <libavfilter/avfilter.h>
63 #include "tvheadend.h"
66 diff -ur tvheadend-4.0.8.orig/src/plumbing/transcoding.c tvheadend-4.0.8/src/plumbing/transcoding.c
67 --- tvheadend-4.0.8.orig/src/plumbing/transcoding.c 2015-12-16 18:33:33.000000000 +0100
68 +++ tvheadend-4.0.8/src/plumbing/transcoding.c 2016-04-16 19:53:13.907273675 +0200
71 #include <libavformat/avformat.h>
72 #include <libavcodec/avcodec.h>
73 -#include <libswscale/swscale.h>
74 +#include <libavfilter/avfiltergraph.h>
75 +#include <libavfilter/buffersink.h>
76 +#include <libavfilter/buffersrc.h>
77 +#include <libavutil/opt.h>
78 #include <libavresample/avresample.h>
79 #include <libavutil/opt.h>
80 #include <libavutil/audio_fifo.h>
81 #include <libavutil/dict.h>
82 -#include <libavutil/audioconvert.h>
84 #if LIBAVUTIL_VERSION_MICRO >= 100 /* FFMPEG */
85 #define USING_FFMPEG 1
89 AVFrame *vid_dec_frame;
90 - struct SwsContext *vid_scaler;
91 AVFrame *vid_enc_frame;
93 + AVFilterGraph *flt_graph;
94 + AVFilterContext *flt_bufsrcctx;
95 + AVFilterContext *flt_bufsinkctx;
100 @@ -952,6 +957,114 @@
104 +/* create a simple deinterlacer-scaler video filter chain */
106 +create_video_filter(video_stream_t *vs, transcoder_t *t,
107 + AVCodecContext *ictx, AVCodecContext *octx)
109 + AVFilterInOut *flt_inputs, *flt_outputs;
110 + AVFilter *flt_bufsrc, *flt_bufsink;
115 + flt_inputs = flt_outputs = NULL;
116 + flt_bufsrc = flt_bufsink = NULL;
119 + avfilter_graph_free(&vs->flt_graph);
121 + vs->flt_graph = avfilter_graph_alloc();
122 + if (!vs->flt_graph)
125 + flt_inputs = avfilter_inout_alloc();
129 + flt_outputs = avfilter_inout_alloc();
133 + flt_bufsrc = avfilter_get_by_name("buffer");
134 + flt_bufsink = avfilter_get_by_name("buffersink");
135 + if (!flt_bufsrc || !flt_bufsink) {
136 + tvherror("transcode", "%04X: libav default buffers unknown", shortid(t));
140 + memset(opt, 0, sizeof(opt));
141 + snprintf(opt, sizeof(opt), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
145 + ictx->time_base.num,
146 + ictx->time_base.den,
147 + ictx->sample_aspect_ratio.num,
148 + ictx->sample_aspect_ratio.den);
150 + err = avfilter_graph_create_filter(&vs->flt_bufsrcctx, flt_bufsrc, "in",
151 + opt, NULL, vs->flt_graph);
153 + tvherror("transcode", "%04X: fltchain IN init error", shortid(t));
157 + err = avfilter_graph_create_filter(&vs->flt_bufsinkctx, flt_bufsink,
158 + "out", NULL, NULL, vs->flt_graph);
160 + tvherror("transcode", "%04X: fltchain OUT init error", shortid(t));
164 + flt_outputs->name = av_strdup("in");
165 + flt_outputs->filter_ctx = vs->flt_bufsrcctx;
166 + flt_outputs->pad_idx = 0;
167 + flt_outputs->next = NULL;
168 + flt_inputs->name = av_strdup("out");
169 + flt_inputs->filter_ctx = vs->flt_bufsinkctx;
170 + flt_inputs->pad_idx = 0;
171 + flt_inputs->next = NULL;
173 + /* add filters: yadif to deinterlace and a scaler */
174 + memset(opt, 0, sizeof(opt));
175 + snprintf(opt, sizeof(opt), "yadif,scale=%dx%d",
178 + err = avfilter_graph_parse_ptr(vs->flt_graph,
184 + tvherror("transcode", "%04X: failed to init filter chain", shortid(t));
188 + err = avfilter_graph_config(vs->flt_graph, NULL);
190 + tvherror("transcode", "%04X: failed to config filter chain", shortid(t));
194 + avfilter_inout_free(&flt_inputs);
195 + avfilter_inout_free(&flt_outputs);
197 + return 0; /* all OK */
201 + avfilter_inout_free(&flt_inputs);
203 + avfilter_inout_free(&flt_outputs);
204 + if (vs->flt_graph) {
205 + avfilter_graph_free(&vs->flt_graph);
206 + vs->flt_graph = NULL;
216 AVCodecContext *ictx, *octx;
218 AVPacket packet, packet2;
219 - AVPicture deint_pic;
220 - uint8_t *buf, *deint;
221 - int length, len, ret, got_picture, got_output, got_ref;
222 + int length, ret, got_picture, got_output, got_ref;
223 video_stream_t *vs = (video_stream_t*)ts;
224 streaming_message_t *sm;
227 icodec = vs->vid_icodec;
228 ocodec = vs->vid_ocodec;
230 - buf = deint = NULL;
234 @@ -1061,7 +1171,7 @@
235 switch (ts->ts_type) {
237 octx->codec_id = AV_CODEC_ID_MPEG2VIDEO;
238 - octx->pix_fmt = PIX_FMT_YUV420P;
239 + octx->pix_fmt = AV_PIX_FMT_YUV420P;
240 octx->flags |= CODEC_FLAG_GLOBAL_HEADER;
242 // Default settings for quantizer. Best quality unless changed by the streaming profile.
243 @@ -1089,7 +1199,7 @@
246 octx->codec_id = AV_CODEC_ID_VP8;
247 - octx->pix_fmt = PIX_FMT_YUV420P;
248 + octx->pix_fmt = AV_PIX_FMT_YUV420P;
250 av_dict_set(&opts, "quality", "realtime", 0);
252 @@ -1120,7 +1230,7 @@
255 octx->codec_id = AV_CODEC_ID_H264;
256 - octx->pix_fmt = PIX_FMT_YUV420P;
257 + octx->pix_fmt = AV_PIX_FMT_YUV420P;
258 octx->flags |= CODEC_FLAG_GLOBAL_HEADER;
260 // Qscale difference between I-frames and P-frames.
261 @@ -1177,79 +1287,53 @@
262 transcoder_stream_invalidate(ts);
267 - len = avpicture_get_size(ictx->pix_fmt, ictx->width, ictx->height);
268 - deint = av_malloc(len);
270 - avpicture_fill(&deint_pic,
276 - if (avpicture_deinterlace(&deint_pic,
277 - (AVPicture *)vs->vid_dec_frame,
280 - ictx->height) < 0) {
281 - tvherror("transcode", "%04X: Cannot deinterlace frame", shortid(t));
282 - transcoder_stream_invalidate(ts);
284 + if (create_video_filter(vs, t, ictx, octx)) {
285 + tvherror("transcode", "%04X: Video filter creation failed",
287 + transcoder_stream_invalidate(ts);
292 - len = avpicture_get_size(octx->pix_fmt, octx->width, octx->height);
293 - buf = av_malloc(len + FF_INPUT_BUFFER_PADDING_SIZE);
294 - memset(buf, 0, len);
296 - avpicture_fill((AVPicture *)vs->vid_enc_frame,
302 - vs->vid_scaler = sws_getCachedContext(vs->vid_scaler,
314 - if (sws_scale(vs->vid_scaler,
315 - (const uint8_t * const*)deint_pic.data,
316 - deint_pic.linesize,
319 - vs->vid_enc_frame->data,
320 - vs->vid_enc_frame->linesize) < 0) {
321 - tvherror("transcode", "%04X: Cannot scale frame", shortid(t));
322 + /* push decoded frame into filter chain */
323 + if (av_buffersrc_add_frame(vs->flt_bufsrcctx, vs->vid_dec_frame) < 0) {
324 + tvherror("transcode", "%04X: filter input error", shortid(t));
325 transcoder_stream_invalidate(ts);
329 - vs->vid_enc_frame->format = octx->pix_fmt;
330 - vs->vid_enc_frame->width = octx->width;
331 - vs->vid_enc_frame->height = octx->height;
333 - vs->vid_enc_frame->pkt_pts = vs->vid_dec_frame->pkt_pts;
334 - vs->vid_enc_frame->pkt_dts = vs->vid_dec_frame->pkt_dts;
336 - if (vs->vid_dec_frame->reordered_opaque != AV_NOPTS_VALUE)
337 - vs->vid_enc_frame->pts = vs->vid_dec_frame->reordered_opaque;
339 - else if (ictx->coded_frame && ictx->coded_frame->pts != AV_NOPTS_VALUE)
340 - vs->vid_enc_frame->pts = vs->vid_dec_frame->pts;
342 - ret = avcodec_encode_video2(octx, &packet2, vs->vid_enc_frame, &got_output);
344 - tvherror("transcode", "%04X: Error encoding frame", shortid(t));
345 - transcoder_stream_invalidate(ts);
347 + /* and pull out a filtered frame */
349 + ret = av_buffersink_get_frame(vs->flt_bufsinkctx, vs->vid_enc_frame);
350 + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
353 + tvherror("transcode", "%04X: filter output error", shortid(t));
354 + transcoder_stream_invalidate(ts);
358 + vs->vid_enc_frame->format = octx->pix_fmt;
359 + vs->vid_enc_frame->width = octx->width;
360 + vs->vid_enc_frame->height = octx->height;
362 + vs->vid_enc_frame->pkt_pts = vs->vid_dec_frame->pkt_pts;
363 + vs->vid_enc_frame->pkt_dts = vs->vid_dec_frame->pkt_dts;
365 + if (vs->vid_dec_frame->reordered_opaque != AV_NOPTS_VALUE)
366 + vs->vid_enc_frame->pts = vs->vid_dec_frame->reordered_opaque;
368 + else if (ictx->coded_frame && ictx->coded_frame->pts != AV_NOPTS_VALUE)
369 + vs->vid_enc_frame->pts = vs->vid_dec_frame->pts;
371 + ret = avcodec_encode_video2(octx, &packet2, vs->vid_enc_frame, &got_output);
373 + tvherror("transcode", "%04X: Error encoding frame", shortid(t));
374 + transcoder_stream_invalidate(ts);
377 + av_frame_unref(vs->vid_enc_frame);
381 @@ -1263,12 +1347,6 @@
383 av_free_packet(&packet);
394 @@ -1548,15 +1626,17 @@
395 if(vs->vid_dec_frame)
396 av_free(vs->vid_dec_frame);
399 - sws_freeContext(vs->vid_scaler);
401 if(vs->vid_enc_frame)
402 av_free(vs->vid_enc_frame);
404 if (vs->vid_first_pkt)
405 pkt_ref_dec(vs->vid_first_pkt);
407 + if (vs->flt_graph) {
408 + avfilter_graph_free(&vs->flt_graph);
409 + vs->flt_graph = NULL;
415 @@ -1603,11 +1683,13 @@
416 vs->vid_ictx->thread_count =
417 vs->vid_octx->thread_count = transcoder_thread_count(t, sct);
419 - vs->vid_dec_frame = avcodec_alloc_frame();
420 - vs->vid_enc_frame = avcodec_alloc_frame();
421 + vs->vid_dec_frame = av_frame_alloc();
422 + vs->vid_enc_frame = av_frame_alloc();
424 + av_frame_unref(vs->vid_dec_frame);
425 + av_frame_unref(vs->vid_enc_frame);
427 - avcodec_get_frame_defaults(vs->vid_dec_frame);
428 - avcodec_get_frame_defaults(vs->vid_enc_frame);
429 + vs->flt_graph = NULL; /* allocated in packet processor */
431 LIST_INSERT_HEAD(&t->t_stream_list, (transcoder_stream_t*)vs, ts_link);