Merge pull request #2847 from elupus/vda_ffmpeg
[vuplus_xbmc] / xbmc / cores / dvdplayer / DVDCodecs / Video / DVDVideoCodecFFmpeg.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://www.xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "system.h"
22 #if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS)
23   #include "config.h"
24 #endif
25 #include "DVDVideoCodecFFmpeg.h"
26 #include "DVDDemuxers/DVDDemux.h"
27 #include "DVDStreamInfo.h"
28 #include "DVDClock.h"
29 #include "DVDCodecs/DVDCodecs.h"
30 #include "DVDCodecs/DVDCodecUtils.h"
31 #include "DVDVideoPPFFmpeg.h"
32 #if defined(TARGET_POSIX) || defined(TARGET_WINDOWS)
33 #include "utils/CPUInfo.h"
34 #endif
35 #include "settings/AdvancedSettings.h"
36 #include "settings/Settings.h"
37 #include "utils/log.h"
38 #include "boost/shared_ptr.hpp"
39 #include "threads/Atomics.h"
40
41 #ifndef TARGET_POSIX
42 #define RINT(x) ((x) >= 0 ? ((int)((x) + 0.5)) : ((int)((x) - 0.5)))
43 #else
44 #include <math.h>
45 #define RINT lrint
46 #endif
47
48 #include "cores/VideoRenderers/RenderManager.h"
49 #include "cores/VideoRenderers/RenderFormats.h"
50
51 #ifdef HAVE_LIBVDPAU
52 #include "VDPAU.h"
53 #endif
54 #ifdef HAS_DX
55 #include "DXVA.h"
56 #endif
57 #ifdef HAVE_LIBVA
58 #include "VAAPI.h"
59 #endif
60 #ifdef TARGET_DARWIN_OSX
61 #include "VDA.h"
62 #endif
63
64 using namespace boost;
65
66 enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx
67                                                 , const PixelFormat * fmt )
68 {
69   CDVDVideoCodecFFmpeg* ctx  = (CDVDVideoCodecFFmpeg*)avctx->opaque;
70
71   if(!ctx->IsHardwareAllowed())
72     return ctx->m_dllAvCodec.avcodec_default_get_format(avctx, fmt);
73
74   const PixelFormat * cur = fmt;
75   while(*cur != PIX_FMT_NONE)
76   {
77 #ifdef HAVE_LIBVDPAU
78     if(CVDPAU::IsVDPAUFormat(*cur) && CSettings::Get().GetBool("videoplayer.usevdpau"))
79     {
80       CLog::Log(LOGNOTICE,"CDVDVideoCodecFFmpeg::GetFormat - Creating VDPAU(%ix%i)", avctx->width, avctx->height);
81       CVDPAU* vdp = new CVDPAU();
82       if(vdp->Open(avctx, *cur))
83       {
84         ctx->SetHardware(vdp);
85         return *cur;
86       }
87       else
88         vdp->Release();
89     }
90 #endif
91 #ifdef HAS_DX
92   if(DXVA::CDecoder::Supports(*cur) && CSettings::Get().GetBool("videoplayer.usedxva2"))
93   {
94     DXVA::CDecoder* dec = new DXVA::CDecoder();
95     if(dec->Open(avctx, *cur, ctx->m_uSurfacesCount))
96     {
97       ctx->SetHardware(dec);
98       return *cur;
99     }
100     else
101       dec->Release();
102   }
103 #endif
104 #ifdef HAVE_LIBVA
105     // mpeg4 vaapi decoding is disabled
106     if(*cur == PIX_FMT_VAAPI_VLD && CSettings::Get().GetBool("videoplayer.usevaapi") 
107     && (avctx->codec_id != CODEC_ID_MPEG4 || g_advancedSettings.m_videoAllowMpeg4VAAPI)) 
108     {
109       if (ctx->GetHardware() != NULL)
110       {
111         ctx->SetHardware(NULL);
112       }
113
114       VAAPI::CDecoder* dec = new VAAPI::CDecoder();
115       if(dec->Open(avctx, *cur, ctx->m_uSurfacesCount))
116       {
117         ctx->SetHardware(dec);
118         return *cur;
119       }
120       else
121         dec->Release();
122     }
123 #endif
124
125 #ifdef TARGET_DARWIN_OSX
126     if (*cur == AV_PIX_FMT_VDA_VLD && CSettings::Get().GetBool("videoplayer.usevda"))
127     {
128       VDA::CDecoder* dec = new VDA::CDecoder();
129       if(dec->Open(avctx, *cur, ctx->m_uSurfacesCount))
130       {
131         ctx->SetHardware(dec);
132         return *cur;
133       }
134       else
135         dec->Release();
136     }
137 #endif
138     cur++;
139   }
140   return ctx->m_dllAvCodec.avcodec_default_get_format(avctx, fmt);
141 }
142
143 CDVDVideoCodecFFmpeg::CDVDVideoCodecFFmpeg() : CDVDVideoCodec()
144 {
145   m_pCodecContext = NULL;
146   m_pFrame = NULL;
147   m_pFilterGraph  = NULL;
148   m_pFilterIn     = NULL;
149   m_pFilterOut    = NULL;
150   m_pBufferRef    = NULL;
151
152   m_iPictureWidth = 0;
153   m_iPictureHeight = 0;
154
155   m_uSurfacesCount = 0;
156
157   m_iScreenWidth = 0;
158   m_iScreenHeight = 0;
159   m_iOrientation = 0;
160   m_bSoftware = false;
161   m_isHi10p = false;
162   m_pHardware = NULL;
163   m_iLastKeyframe = 0;
164   m_dts = DVD_NOPTS_VALUE;
165   m_started = false;
166 }
167
168 CDVDVideoCodecFFmpeg::~CDVDVideoCodecFFmpeg()
169 {
170   Dispose();
171 }
172
173 bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
174 {
175   AVCodec* pCodec;
176
177   if(!m_dllAvUtil.Load()
178   || !m_dllAvCodec.Load()
179   || !m_dllSwScale.Load()
180   || !m_dllPostProc.Load()
181   || !m_dllAvFilter.Load()
182   ) return false;
183
184   m_dllAvCodec.avcodec_register_all();
185   m_dllAvFilter.avfilter_register_all();
186
187   m_bSoftware     = hints.software;
188   m_iOrientation  = hints.orientation;
189
190   for(std::vector<ERenderFormat>::iterator it = options.m_formats.begin(); it != options.m_formats.end(); ++it)
191   {
192     m_formats.push_back((PixelFormat)CDVDCodecUtils::PixfmtFromEFormat(*it));
193     if(*it == RENDER_FMT_YUV420P)
194       m_formats.push_back(PIX_FMT_YUVJ420P);
195   }
196   m_formats.push_back(PIX_FMT_NONE); /* always add none to get a terminated list in ffmpeg world */
197
198   pCodec = NULL;
199   m_pCodecContext = NULL;
200
201   if (hints.codec == CODEC_ID_H264)
202   {
203     switch(hints.profile)
204     {
205       case FF_PROFILE_H264_HIGH_10:
206       case FF_PROFILE_H264_HIGH_10_INTRA:
207       case FF_PROFILE_H264_HIGH_422:
208       case FF_PROFILE_H264_HIGH_422_INTRA:
209       case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
210       case FF_PROFILE_H264_HIGH_444_INTRA:
211       case FF_PROFILE_H264_CAVLC_444:
212       // this is needed to not open the decoders
213       m_bSoftware = true;
214       // this we need to enable multithreading for hi10p via advancedsettings
215       m_isHi10p = true;
216       break;
217     }
218   }
219
220   if(pCodec == NULL)
221     pCodec = m_dllAvCodec.avcodec_find_decoder(hints.codec);
222
223   if(pCodec == NULL)
224   {
225     CLog::Log(LOGDEBUG,"CDVDVideoCodecFFmpeg::Open() Unable to find codec %d", hints.codec);
226     return false;
227   }
228
229   CLog::Log(LOGNOTICE,"CDVDVideoCodecFFmpeg::Open() Using codec: %s",pCodec->long_name ? pCodec->long_name : pCodec->name);
230
231   if(m_pCodecContext == NULL)
232     m_pCodecContext = m_dllAvCodec.avcodec_alloc_context3(pCodec);
233
234   m_pCodecContext->opaque = (void*)this;
235   m_pCodecContext->debug_mv = 0;
236   m_pCodecContext->debug = 0;
237   m_pCodecContext->workaround_bugs = FF_BUG_AUTODETECT;
238   m_pCodecContext->get_format = GetFormat;
239   m_pCodecContext->codec_tag = hints.codec_tag;
240   /* Only allow slice threading, since frame threading is more
241    * sensitive to changes in frame sizes, and it causes crashes
242    * during HW accell - so we unset it in this case.
243    *
244    * When we detect Hi10p and user did not disable hi10pmultithreading
245    * via advancedsettings.xml we keep the ffmpeg default thread type.
246    * */
247   if(m_isHi10p && !g_advancedSettings.m_videoDisableHi10pMultithreading)
248   {
249     CLog::Log(LOGDEBUG,"CDVDVideoCodecFFmpeg::Open() Keep default threading for Hi10p: %d",
250                         m_pCodecContext->thread_type);
251   }
252   else
253     m_pCodecContext->thread_type = FF_THREAD_SLICE;
254
255 #if defined(TARGET_DARWIN_IOS)
256   // ffmpeg with enabled neon will crash and burn if this is enabled
257   m_pCodecContext->flags &= CODEC_FLAG_EMU_EDGE;
258 #else
259   if (pCodec->id != CODEC_ID_H264 && pCodec->capabilities & CODEC_CAP_DR1
260       && pCodec->id != CODEC_ID_VP8
261      )
262     m_pCodecContext->flags |= CODEC_FLAG_EMU_EDGE;
263 #endif
264
265   // if we don't do this, then some codecs seem to fail.
266   m_pCodecContext->coded_height = hints.height;
267   m_pCodecContext->coded_width = hints.width;
268   m_pCodecContext->bits_per_coded_sample = hints.bitsperpixel;
269
270   if( hints.extradata && hints.extrasize > 0 )
271   {
272     m_pCodecContext->extradata_size = hints.extrasize;
273     m_pCodecContext->extradata = (uint8_t*)m_dllAvUtil.av_mallocz(hints.extrasize + FF_INPUT_BUFFER_PADDING_SIZE);
274     memcpy(m_pCodecContext->extradata, hints.extradata, hints.extrasize);
275   }
276
277   // advanced setting override for skip loop filter (see avcodec.h for valid options)
278   // TODO: allow per video setting?
279   if (g_advancedSettings.m_iSkipLoopFilter != 0)
280   {
281     m_pCodecContext->skip_loop_filter = (AVDiscard)g_advancedSettings.m_iSkipLoopFilter;
282   }
283
284   // set any special options
285   for(std::vector<CDVDCodecOption>::iterator it = options.m_keys.begin(); it != options.m_keys.end(); ++it)
286   {
287     if (it->m_name == "surfaces")
288       m_uSurfacesCount = std::atoi(it->m_value.c_str());
289     else
290       m_dllAvUtil.av_opt_set(m_pCodecContext, it->m_name.c_str(), it->m_value.c_str(), 0);
291   }
292
293   int num_threads = std::min(8 /*MAX_THREADS*/, g_cpuInfo.getCPUCount());
294   if( num_threads > 1 && !hints.software && m_pHardware == NULL // thumbnail extraction fails when run threaded
295   && ( pCodec->id == CODEC_ID_H264
296     || pCodec->id == CODEC_ID_MPEG4 ))
297     m_pCodecContext->thread_count = num_threads;
298
299   if (m_dllAvCodec.avcodec_open2(m_pCodecContext, pCodec, NULL) < 0)
300   {
301     CLog::Log(LOGDEBUG,"CDVDVideoCodecFFmpeg::Open() Unable to open codec");
302     return false;
303   }
304
305   m_pFrame = m_dllAvCodec.avcodec_alloc_frame();
306   if (!m_pFrame) return false;
307
308   UpdateName();
309   return true;
310 }
311
312 void CDVDVideoCodecFFmpeg::Dispose()
313 {
314   if (m_pFrame) m_dllAvUtil.av_free(m_pFrame);
315   m_pFrame = NULL;
316
317   if (m_pCodecContext)
318   {
319     if (m_pCodecContext->codec) m_dllAvCodec.avcodec_close(m_pCodecContext);
320     if (m_pCodecContext->extradata)
321     {
322       m_dllAvUtil.av_free(m_pCodecContext->extradata);
323       m_pCodecContext->extradata = NULL;
324       m_pCodecContext->extradata_size = 0;
325     }
326     m_dllAvUtil.av_free(m_pCodecContext);
327     m_pCodecContext = NULL;
328   }
329   SAFE_RELEASE(m_pHardware);
330
331   FilterClose();
332
333   m_dllAvCodec.Unload();
334   m_dllAvUtil.Unload();
335   m_dllAvFilter.Unload();
336   m_dllPostProc.Unload();
337 }
338
339 void CDVDVideoCodecFFmpeg::SetDropState(bool bDrop)
340 {
341   if( m_pCodecContext )
342   {
343     // i don't know exactly how high this should be set
344     // couldn't find any good docs on it. think it varies
345     // from codec to codec on what it does
346
347     //  2 seem to be to high.. it causes video to be ruined on following images
348     if( bDrop )
349     {
350       m_pCodecContext->skip_frame = AVDISCARD_NONREF;
351       m_pCodecContext->skip_idct = AVDISCARD_NONREF;
352       m_pCodecContext->skip_loop_filter = AVDISCARD_NONREF;
353     }
354     else
355     {
356       m_pCodecContext->skip_frame = AVDISCARD_DEFAULT;
357       m_pCodecContext->skip_idct = AVDISCARD_DEFAULT;
358       m_pCodecContext->skip_loop_filter = AVDISCARD_DEFAULT;
359     }
360   }
361 }
362
363 unsigned int CDVDVideoCodecFFmpeg::SetFilters(unsigned int flags)
364 {
365   m_filters_next.Empty();
366
367   if(m_pHardware)
368     return 0;
369
370   if(flags & FILTER_ROTATE)
371   {
372     switch(m_iOrientation)
373     {
374       case 90:
375         m_filters_next += "transpose=1";
376         break;
377       case 180:
378         m_filters_next += "vflip,hflip";
379         break;
380       case 270:  
381         m_filters_next += "transpose=2";
382         break;
383       default:
384         break;
385       }
386   }
387
388   if(flags & FILTER_DEINTERLACE_YADIF)
389   {
390     if(flags & FILTER_DEINTERLACE_HALFED)
391       m_filters_next = "yadif=0:-1";
392     else
393       m_filters_next = "yadif=1:-1";
394
395     if(flags & FILTER_DEINTERLACE_FLAGGED)
396       m_filters_next += ":1";
397
398     flags &= ~FILTER_DEINTERLACE_ANY | FILTER_DEINTERLACE_YADIF;
399   }
400
401   return flags;
402 }
403
404 union pts_union
405 {
406   double  pts_d;
407   int64_t pts_i;
408 };
409
410 static int64_t pts_dtoi(double pts)
411 {
412   pts_union u;
413   u.pts_d = pts;
414   return u.pts_i;
415 }
416
417 static double pts_itod(int64_t pts)
418 {
419   pts_union u;
420   u.pts_i = pts;
421   return u.pts_d;
422 }
423
424 int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double pts)
425 {
426   int iGotPicture = 0, len = 0;
427
428   if (!m_pCodecContext)
429     return VC_ERROR;
430
431   if(pData)
432     m_iLastKeyframe++;
433
434   shared_ptr<CSingleLock> lock;
435   if(m_pHardware)
436   {
437     CCriticalSection* section = m_pHardware->Section();
438     if(section)
439       lock = shared_ptr<CSingleLock>(new CSingleLock(*section));
440
441     int result;
442     if(pData)
443       result = m_pHardware->Check(m_pCodecContext);
444     else
445       result = m_pHardware->Decode(m_pCodecContext, NULL);
446
447     if(result)
448       return result;
449   }
450
451   if(m_pFilterGraph)
452   {
453     int result = 0;
454     if(pData == NULL)
455       result = FilterProcess(NULL);
456     if(result)
457       return result;
458   }
459
460   m_dts = dts;
461   m_pCodecContext->reordered_opaque = pts_dtoi(pts);
462
463   AVPacket avpkt;
464   m_dllAvCodec.av_init_packet(&avpkt);
465   avpkt.data = pData;
466   avpkt.size = iSize;
467   /* We lie, but this flag is only used by pngdec.c.
468    * Setting it correctly would allow CorePNG decoding. */
469   avpkt.flags = AV_PKT_FLAG_KEY;
470   len = m_dllAvCodec.avcodec_decode_video2(m_pCodecContext, m_pFrame, &iGotPicture, &avpkt);
471
472   if(m_iLastKeyframe < m_pCodecContext->has_b_frames + 2)
473     m_iLastKeyframe = m_pCodecContext->has_b_frames + 2;
474
475   if (len < 0)
476   {
477     CLog::Log(LOGERROR, "%s - avcodec_decode_video returned failure", __FUNCTION__);
478     return VC_ERROR;
479   }
480
481   if (!iGotPicture)
482     return VC_BUFFER;
483
484   if(m_pFrame->key_frame)
485   {
486     m_started = true;
487     m_iLastKeyframe = m_pCodecContext->has_b_frames + 2;
488   }
489
490   /* put a limit on convergence count to avoid huge mem usage on streams without keyframes */
491   if(m_iLastKeyframe > 300)
492     m_iLastKeyframe = 300;
493
494   /* h264 doesn't always have keyframes + won't output before first keyframe anyway */
495   if(m_pCodecContext->codec_id == CODEC_ID_H264
496   || m_pCodecContext->codec_id == CODEC_ID_SVQ3)
497     m_started = true;
498
499   if(m_pHardware == NULL)
500   {
501     bool need_scale = std::find( m_formats.begin()
502                                , m_formats.end()
503                                , m_pCodecContext->pix_fmt) == m_formats.end();
504
505     bool need_reopen  = false;
506     if(!m_filters.Equals(m_filters_next))
507       need_reopen = true;
508
509     if(m_pFilterIn)
510     {
511       if(m_pFilterIn->outputs[0]->format != m_pCodecContext->pix_fmt
512       || m_pFilterIn->outputs[0]->w      != m_pCodecContext->width
513       || m_pFilterIn->outputs[0]->h      != m_pCodecContext->height)
514         need_reopen = true;
515     }
516
517     // try to setup new filters
518     if (need_reopen || (need_scale && m_pFilterGraph == NULL))
519     {
520       m_filters = m_filters_next;
521
522       if(FilterOpen(m_filters, need_scale) < 0)
523         FilterClose();
524     }
525   }
526
527   int result;
528   if(m_pHardware)
529     result = m_pHardware->Decode(m_pCodecContext, m_pFrame);
530   else if(m_pFilterGraph)
531     result = FilterProcess(m_pFrame);
532   else
533     result = VC_PICTURE | VC_BUFFER;
534
535   if(result & VC_FLUSHED)
536     Reset();
537
538   return result;
539 }
540
541 void CDVDVideoCodecFFmpeg::Reset()
542 {
543   m_started = false;
544   m_iLastKeyframe = m_pCodecContext->has_b_frames;
545   m_dllAvCodec.avcodec_flush_buffers(m_pCodecContext);
546
547   if (m_pHardware)
548     m_pHardware->Reset();
549
550   m_filters = "";
551   FilterClose();
552 }
553
554 bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture)
555 {
556   pDvdVideoPicture->iWidth = m_pCodecContext->width;
557   pDvdVideoPicture->iHeight = m_pCodecContext->height;
558
559   if(m_pBufferRef)
560   {
561     pDvdVideoPicture->iWidth  = m_pBufferRef->video->w;
562     pDvdVideoPicture->iHeight = m_pBufferRef->video->h;
563   }
564
565   /* crop of 10 pixels if demuxer asked it */
566   if(m_pCodecContext->coded_width  && m_pCodecContext->coded_width  < (int)pDvdVideoPicture->iWidth
567                                    && m_pCodecContext->coded_width  > (int)pDvdVideoPicture->iWidth  - 10)
568     pDvdVideoPicture->iWidth = m_pCodecContext->coded_width;
569
570   if(m_pCodecContext->coded_height && m_pCodecContext->coded_height < (int)pDvdVideoPicture->iHeight
571                                    && m_pCodecContext->coded_height > (int)pDvdVideoPicture->iHeight - 10)
572     pDvdVideoPicture->iHeight = m_pCodecContext->coded_height;
573
574   double aspect_ratio;
575
576   /* use variable in the frame */
577   AVRational pixel_aspect = m_pCodecContext->sample_aspect_ratio;
578   if (m_pBufferRef)
579     pixel_aspect = m_pBufferRef->video->sample_aspect_ratio;
580
581   if (pixel_aspect.num == 0)
582     aspect_ratio = 0;
583   else
584     aspect_ratio = av_q2d(pixel_aspect) * pDvdVideoPicture->iWidth / pDvdVideoPicture->iHeight;
585
586   if (aspect_ratio <= 0.0)
587     aspect_ratio = (float)pDvdVideoPicture->iWidth / (float)pDvdVideoPicture->iHeight;
588
589   /* XXX: we suppose the screen has a 1.0 pixel ratio */ // CDVDVideo will compensate it.
590   pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight;
591   pDvdVideoPicture->iDisplayWidth  = ((int)RINT(pDvdVideoPicture->iHeight * aspect_ratio)) & -3;
592   if (pDvdVideoPicture->iDisplayWidth > pDvdVideoPicture->iWidth)
593   {
594     pDvdVideoPicture->iDisplayWidth  = pDvdVideoPicture->iWidth;
595     pDvdVideoPicture->iDisplayHeight = ((int)RINT(pDvdVideoPicture->iWidth / aspect_ratio)) & -3;
596   }
597
598
599   pDvdVideoPicture->pts = DVD_NOPTS_VALUE;
600
601   if (!m_pFrame)
602     return false;
603
604   pDvdVideoPicture->iRepeatPicture = 0.5 * m_pFrame->repeat_pict;
605   pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
606   pDvdVideoPicture->iFlags |= m_pFrame->interlaced_frame ? DVP_FLAG_INTERLACED : 0;
607   pDvdVideoPicture->iFlags |= m_pFrame->top_field_first ? DVP_FLAG_TOP_FIELD_FIRST: 0;
608
609   pDvdVideoPicture->chroma_position = m_pCodecContext->chroma_sample_location;
610   pDvdVideoPicture->color_primaries = m_pCodecContext->color_primaries;
611   pDvdVideoPicture->color_transfer = m_pCodecContext->color_trc;
612   if(m_pCodecContext->color_range == AVCOL_RANGE_JPEG
613   || m_pCodecContext->pix_fmt     == PIX_FMT_YUVJ420P)
614     pDvdVideoPicture->color_range = 1;
615   else
616     pDvdVideoPicture->color_range = 0;
617
618   pDvdVideoPicture->qscale_table = m_pFrame->qscale_table;
619   pDvdVideoPicture->qscale_stride = m_pFrame->qstride;
620
621   switch (m_pFrame->qscale_type) {
622   case FF_QSCALE_TYPE_MPEG1:
623     pDvdVideoPicture->qscale_type = DVP_QSCALE_MPEG1;
624     break;
625   case FF_QSCALE_TYPE_MPEG2:
626     pDvdVideoPicture->qscale_type = DVP_QSCALE_MPEG2;
627     break;
628   case FF_QSCALE_TYPE_H264:
629     pDvdVideoPicture->qscale_type = DVP_QSCALE_H264;
630     break;
631   default:
632     pDvdVideoPicture->qscale_type = DVP_QSCALE_UNKNOWN;
633   }
634
635   pDvdVideoPicture->dts = m_dts;
636   m_dts = DVD_NOPTS_VALUE;
637   if (m_pFrame->reordered_opaque)
638     pDvdVideoPicture->pts = pts_itod(m_pFrame->reordered_opaque);
639   else
640     pDvdVideoPicture->pts = DVD_NOPTS_VALUE;
641
642   if(!m_started)
643     pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
644
645   return true;
646 }
647
648 bool CDVDVideoCodecFFmpeg::GetPicture(DVDVideoPicture* pDvdVideoPicture)
649 {
650   if(m_pHardware)
651     return m_pHardware->GetPicture(m_pCodecContext, m_pFrame, pDvdVideoPicture);
652
653   if(!GetPictureCommon(pDvdVideoPicture))
654     return false;
655
656   {
657     for (int i = 0; i < 4; i++)
658       pDvdVideoPicture->data[i]      = m_pFrame->data[i];
659     for (int i = 0; i < 4; i++)
660       pDvdVideoPicture->iLineSize[i] = m_pFrame->linesize[i];
661   }
662
663   pDvdVideoPicture->iFlags |= pDvdVideoPicture->data[0] ? 0 : DVP_FLAG_DROPPED;
664   pDvdVideoPicture->extended_format = 0;
665
666   PixelFormat pix_fmt;
667   if(m_pBufferRef)
668     pix_fmt = (PixelFormat)m_pBufferRef->format;
669   else
670     pix_fmt = m_pCodecContext->pix_fmt;
671
672   pDvdVideoPicture->format = CDVDCodecUtils::EFormatFromPixfmt(pix_fmt);
673   return true;
674 }
675
676 int CDVDVideoCodecFFmpeg::FilterOpen(const CStdString& filters, bool scale)
677 {
678   int result;
679   AVBufferSinkParams *buffersink_params;
680
681   if (m_pFilterGraph)
682     FilterClose();
683
684   if (filters.IsEmpty() && !scale)
685     return 0;
686
687   if (m_pHardware)
688   {
689     CLog::Log(LOGWARNING, "CDVDVideoCodecFFmpeg::FilterOpen - skipped opening filters on hardware decode");
690     return 0;
691   }
692
693   if (!(m_pFilterGraph = m_dllAvFilter.avfilter_graph_alloc()))
694   {
695     CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterOpen - unable to alloc filter graph");
696     return -1;
697   }
698
699   AVFilter* srcFilter = m_dllAvFilter.avfilter_get_by_name("buffer");
700   AVFilter* outFilter = m_dllAvFilter.avfilter_get_by_name("buffersink"); // should be last filter in the graph for now
701
702   CStdString args;
703
704   args.Format("%d:%d:%d:%d:%d:%d:%d",
705     m_pCodecContext->width,
706     m_pCodecContext->height,
707     m_pCodecContext->pix_fmt,
708     m_pCodecContext->time_base.num,
709     m_pCodecContext->time_base.den,
710     m_pCodecContext->sample_aspect_ratio.num,
711     m_pCodecContext->sample_aspect_ratio.den);
712
713   if ((result = m_dllAvFilter.avfilter_graph_create_filter(&m_pFilterIn, srcFilter, "src", args, NULL, m_pFilterGraph)) < 0)
714   {
715     CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterOpen - avfilter_graph_create_filter: src");
716     return result;
717   }
718
719   buffersink_params = m_dllAvFilter.av_buffersink_params_alloc();
720   buffersink_params->pixel_fmts = &m_formats[0];
721 #ifdef FF_API_OLD_VSINK_API
722   if ((result = m_dllAvFilter.avfilter_graph_create_filter(&m_pFilterOut, outFilter, "out", NULL, (void*)buffersink_params->pixel_fmts, m_pFilterGraph)) < 0)
723 #else
724   if ((result = m_dllAvFilter.avfilter_graph_create_filter(&m_pFilterOut, outFilter, "out", NULL, buffersink_params, m_pFilterGraph)) < 0)
725 #endif
726   {
727     m_dllAvUtil.av_freep(&buffersink_params);
728     CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterOpen - avfilter_graph_create_filter: out");
729     return result;
730   }
731   m_dllAvUtil.av_freep(&buffersink_params);
732
733   if (!filters.empty())
734   {
735     AVFilterInOut* outputs = m_dllAvFilter.avfilter_inout_alloc();
736     AVFilterInOut* inputs  = m_dllAvFilter.avfilter_inout_alloc();
737
738     outputs->name    = m_dllAvUtil.av_strdup("in");
739     outputs->filter_ctx = m_pFilterIn;
740     outputs->pad_idx = 0;
741     outputs->next    = NULL;
742
743     inputs->name    = m_dllAvUtil.av_strdup("out");
744     inputs->filter_ctx = m_pFilterOut;
745     inputs->pad_idx = 0;
746     inputs->next    = NULL;
747
748     if ((result = m_dllAvFilter.avfilter_graph_parse(m_pFilterGraph, (const char*)m_filters.c_str(), &inputs, &outputs, NULL)) < 0)
749     {
750       CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterOpen - avfilter_graph_parse");
751       return result;
752     }
753
754     m_dllAvFilter.avfilter_inout_free(&outputs);
755     m_dllAvFilter.avfilter_inout_free(&inputs);
756   }
757   else
758   {
759     if ((result = m_dllAvFilter.avfilter_link(m_pFilterIn, 0, m_pFilterOut, 0)) < 0)
760     {
761       CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterOpen - avfilter_link");
762       return result;
763     }
764   }
765
766   if ((result = m_dllAvFilter.avfilter_graph_config(m_pFilterGraph, NULL)) < 0)
767   {
768     CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterOpen - avfilter_graph_config");
769     return result;
770   }
771
772   return result;
773 }
774
775 void CDVDVideoCodecFFmpeg::FilterClose()
776 {
777   if(m_pBufferRef)
778   {
779     m_dllAvFilter.avfilter_unref_buffer(m_pBufferRef);
780     m_pBufferRef = NULL;
781   }
782
783   if (m_pFilterGraph)
784   {
785     m_dllAvFilter.avfilter_graph_free(&m_pFilterGraph);
786
787     // Disposed by above code
788     m_pFilterIn   = NULL;
789     m_pFilterOut  = NULL;
790   }
791 }
792
793 int CDVDVideoCodecFFmpeg::FilterProcess(AVFrame* frame)
794 {
795   int result, frames;
796
797   if (frame)
798   {
799 #if (defined(LIBAVFILTER_FROM_LIBAV) && LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(3,5,0)) || \
800     (defined(LIBAVFILTER_FROM_FFMPEG) && LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(3,43,100))
801     // API changed in:
802     // ffmpeg: commit 7e350379f87e7f74420b4813170fe808e2313911 (28 Nov 2012)
803     //         not released (post 1.2)
804     // libav: commit 7e350379f87e7f74420b4813170fe808e2313911 (28 Nov 2012)
805     //        release v9 (5 January 2013)
806     result = m_dllAvFilter.av_buffersrc_add_frame(m_pFilterIn, frame);
807 #elif defined(LIBAVFILTER_FROM_FFMPEG) && LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,72,105)
808     // API changed in:
809     // ffmpeg: commit 7bac2a78c2241df4bcc1665703bb71afd9a3e692 (28 Apr 2012)
810     //         release 0.11 (25 May 2012)
811     result = m_dllAvFilter.av_buffersrc_add_frame(m_pFilterIn, frame, 0);
812 #else
813     result = m_dllAvFilter.av_vsrc_buffer_add_frame(m_pFilterIn, frame, 0);
814 #endif
815     if (result < 0)
816     {
817       CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterProcess - av_buffersrc_add_frame/av_vsrc_buffer_add_frame");
818       return VC_ERROR;
819     }
820   }
821
822   if(m_pBufferRef)
823   {
824     m_dllAvFilter.avfilter_unref_buffer(m_pBufferRef);
825     m_pBufferRef = NULL;
826   }
827
828   if ((frames = m_dllAvFilter.av_buffersink_poll_frame(m_pFilterOut)) < 0)
829   {
830     CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterProcess - av_buffersink_poll_frame");
831     return VC_ERROR;
832   }
833
834   if (frames > 0)
835   {
836
837     result = m_dllAvFilter.av_buffersink_get_buffer_ref(m_pFilterOut, &m_pBufferRef, 0);
838     if(!m_pBufferRef || result < 0)
839     {
840       CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterProcess - cur_buf");
841       return VC_ERROR;
842     }
843
844     if(frame == NULL)
845       m_pFrame->reordered_opaque = 0;
846     else
847       m_pFrame->repeat_pict      = -(frames - 1);
848
849     m_pFrame->interlaced_frame = m_pBufferRef->video->interlaced;
850     m_pFrame->top_field_first  = m_pBufferRef->video->top_field_first;
851
852     memcpy(m_pFrame->linesize, m_pBufferRef->linesize, 4*sizeof(int));
853     memcpy(m_pFrame->data    , m_pBufferRef->data    , 4*sizeof(uint8_t*));
854
855     if(frames > 1)
856       return VC_PICTURE;
857     else
858       return VC_PICTURE | VC_BUFFER;
859   }
860
861   return VC_BUFFER;
862 }
863
864 unsigned CDVDVideoCodecFFmpeg::GetConvergeCount()
865 {
866   if(m_pHardware)
867     return m_iLastKeyframe;
868   else
869     return 0;
870 }
871
872 unsigned CDVDVideoCodecFFmpeg::GetAllowedReferences()
873 {
874   if(m_pHardware)
875     return m_pHardware->GetAllowedReferences();
876   else
877     return 0;
878 }