Merge pull request #4539 from Matricom/amcodec
[vuplus_xbmc] / xbmc / cores / dvdplayer / DVDCodecs / DVDFactoryCodec.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://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 #include "utils/log.h"
23
24 #include "DVDFactoryCodec.h"
25 #include "Video/DVDVideoCodec.h"
26 #include "Audio/DVDAudioCodec.h"
27 #include "Overlay/DVDOverlayCodec.h"
28
29 #if defined(TARGET_DARWIN_OSX)
30 #include "Video/DVDVideoCodecVDA.h"
31 #endif
32 #if defined(HAVE_VIDEOTOOLBOXDECODER)
33 #include "Video/DVDVideoCodecVideoToolBox.h"
34 #endif
35 #include "Video/DVDVideoCodecFFmpeg.h"
36 #include "Video/DVDVideoCodecOpenMax.h"
37 #include "Video/DVDVideoCodecLibMpeg2.h"
38 #include "Video/DVDVideoCodecStageFright.h"
39 #if defined(HAVE_LIBCRYSTALHD)
40 #include "Video/DVDVideoCodecCrystalHD.h"
41 #endif
42 #if defined(HAS_LIBAMCODEC)
43 #include "utils/AMLUtils.h"
44 #include "Video/DVDVideoCodecAmlogic.h"
45 #endif
46 #if defined(TARGET_ANDROID)
47 #include "Video/DVDVideoCodecAndroidMediaCodec.h"
48 #include "android/activity/AndroidFeatures.h"
49 #endif
50 #include "Audio/DVDAudioCodecFFmpeg.h"
51 #include "Audio/DVDAudioCodecLibMad.h"
52 #include "Audio/DVDAudioCodecPcm.h"
53 #include "Audio/DVDAudioCodecLPcm.h"
54 #include "Audio/DVDAudioCodecPassthrough.h"
55 #include "Overlay/DVDOverlayCodecSSA.h"
56 #include "Overlay/DVDOverlayCodecText.h"
57 #include "Overlay/DVDOverlayCodecTX3G.h"
58 #include "Overlay/DVDOverlayCodecFFmpeg.h"
59
60
61 #include "DVDStreamInfo.h"
62 #include "settings/Settings.h"
63 #include "utils/SystemInfo.h"
64 #include "utils/StringUtils.h"
65
66 CDVDVideoCodec* CDVDFactoryCodec::OpenCodec(CDVDVideoCodec* pCodec, CDVDStreamInfo &hints, CDVDCodecOptions &options )
67 {
68   try
69   {
70     CLog::Log(LOGDEBUG, "FactoryCodec - Video: %s - Opening", pCodec->GetName());
71     if( pCodec->Open( hints, options ) )
72     {
73       CLog::Log(LOGDEBUG, "FactoryCodec - Video: %s - Opened", pCodec->GetName());
74       return pCodec;
75     }
76
77     CLog::Log(LOGDEBUG, "FactoryCodec - Video: %s - Failed", pCodec->GetName());
78     pCodec->Dispose();
79     delete pCodec;
80   }
81   catch(...)
82   {
83     CLog::Log(LOGERROR, "FactoryCodec - Video: Failed with exception");
84   }
85   return NULL;
86 }
87
88 CDVDAudioCodec* CDVDFactoryCodec::OpenCodec(CDVDAudioCodec* pCodec, CDVDStreamInfo &hints, CDVDCodecOptions &options )
89 {
90   try
91   {
92     CLog::Log(LOGDEBUG, "FactoryCodec - Audio: %s - Opening", pCodec->GetName());
93     if( pCodec->Open( hints, options ) )
94     {
95       CLog::Log(LOGDEBUG, "FactoryCodec - Audio: %s - Opened", pCodec->GetName());
96       return pCodec;
97     }
98
99     CLog::Log(LOGDEBUG, "FactoryCodec - Audio: %s - Failed", pCodec->GetName());
100     pCodec->Dispose();
101     delete pCodec;
102   }
103   catch(...)
104   {
105     CLog::Log(LOGERROR, "FactoryCodec - Audio: Failed with exception");
106   }
107   return NULL;
108 }
109
110 CDVDOverlayCodec* CDVDFactoryCodec::OpenCodec(CDVDOverlayCodec* pCodec, CDVDStreamInfo &hints, CDVDCodecOptions &options )
111 {
112   try
113   {
114     CLog::Log(LOGDEBUG, "FactoryCodec - Overlay: %s - Opening", pCodec->GetName());
115     if( pCodec->Open( hints, options ) )
116     {
117       CLog::Log(LOGDEBUG, "FactoryCodec - Overlay: %s - Opened", pCodec->GetName());
118       return pCodec;
119     }
120
121     CLog::Log(LOGDEBUG, "FactoryCodec - Overlay: %s - Failed", pCodec->GetName());
122     pCodec->Dispose();
123     delete pCodec;
124   }
125   catch(...)
126   {
127     CLog::Log(LOGERROR, "FactoryCodec - Audio: Failed with exception");
128   }
129   return NULL;
130 }
131
132
133 CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigned int surfaces, const std::vector<ERenderFormat>& formats)
134 {
135   CDVDVideoCodec* pCodec = NULL;
136   CDVDCodecOptions options;
137
138   if(formats.empty())
139     options.m_formats.push_back(RENDER_FMT_YUV420P);
140   else
141     options.m_formats = formats;
142
143   //when support for a hardware decoder is not compiled in
144   //only print it if it's actually available on the platform
145   CStdString hwSupport;
146 #if defined(TARGET_DARWIN_OSX)
147   hwSupport += "VDADecoder:yes ";
148 #endif
149 #if defined(HAVE_VIDEOTOOLBOXDECODER) && defined(TARGET_DARWIN)
150   hwSupport += "VideoToolBoxDecoder:yes ";
151 #elif defined(TARGET_DARWIN)
152   hwSupport += "VideoToolBoxDecoder:no ";
153 #endif
154 #ifdef HAVE_LIBCRYSTALHD
155   hwSupport += "CrystalHD:yes ";
156 #else
157   hwSupport += "CrystalHD:no ";
158 #endif
159 #if defined(HAS_LIBAMCODEC)
160   hwSupport += "AMCodec:yes ";
161 #else
162   hwSupport += "AMCodec:no ";
163 #endif
164 #if defined(TARGET_ANDROID)
165   hwSupport += "MediaCodec:yes ";
166 #else
167   hwSupport += "MediaCodec:no ";
168 #endif
169 #if defined(HAVE_LIBOPENMAX) && defined(TARGET_POSIX)
170   hwSupport += "OpenMax:yes ";
171 #elif defined(TARGET_POSIX)
172   hwSupport += "OpenMax:no ";
173 #endif
174 #if defined(HAS_LIBSTAGEFRIGHT)
175   hwSupport += "libstagefright:yes ";
176 #elif defined(_LINUX)
177   hwSupport += "libstagefright:no ";
178 #endif
179 #if defined(HAVE_LIBVDPAU) && defined(TARGET_POSIX)
180   hwSupport += "VDPAU:yes ";
181 #elif defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
182   hwSupport += "VDPAU:no ";
183 #endif
184 #if defined(TARGET_WINDOWS) && defined(HAS_DX)
185   hwSupport += "DXVA:yes ";
186 #elif defined(TARGET_WINDOWS)
187   hwSupport += "DXVA:no ";
188 #endif
189 #if defined(HAVE_LIBVA) && defined(TARGET_POSIX)
190   hwSupport += "VAAPI:yes ";
191 #elif defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
192   hwSupport += "VAAPI:no ";
193 #endif
194
195   CLog::Log(LOGDEBUG, "CDVDFactoryCodec: compiled in hardware support: %s", hwSupport.c_str());
196
197   if (hint.stills && (hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_MPEG1VIDEO))
198   {
199      // If dvd is an mpeg2 and hint.stills
200      if ( (pCodec = OpenCodec(new CDVDVideoCodecLibMpeg2(), hint, options)) ) return pCodec;
201   }
202
203 #if defined(HAS_LIBAMCODEC)
204   // amcodec can handle dvd playback.
205   if (!hint.software && CSettings::Get().GetBool("videoplayer.useamcodec"))
206   {
207      if ( (pCodec = OpenCodec(new CDVDVideoCodecAmlogic(), hint, options)) ) return pCodec;
208   }
209 #endif
210
211 #if defined(TARGET_DARWIN_OSX)
212   if (!hint.software && CSettings::Get().GetBool("videoplayer.usevda"))
213   {
214     if (hint.codec == AV_CODEC_ID_H264 && !hint.ptsinvalid)
215     {
216       if ( (pCodec = OpenCodec(new CDVDVideoCodecVDA(), hint, options)) ) return pCodec;
217     }
218   }
219 #endif
220
221 #if defined(HAVE_VIDEOTOOLBOXDECODER)
222   if (!hint.software && CSettings::Get().GetBool("videoplayer.usevideotoolbox"))
223   {
224     if (g_sysinfo.HasVideoToolBoxDecoder())
225     {
226       switch(hint.codec)
227       {
228         case AV_CODEC_ID_H264:
229           if (hint.codec == AV_CODEC_ID_H264 && hint.ptsinvalid)
230             break;
231           if ( (pCodec = OpenCodec(new CDVDVideoCodecVideoToolBox(), hint, options)) ) return pCodec;
232         break;
233         default:
234         break;
235       }
236     }
237   }
238 #endif
239
240 #if defined(HAVE_LIBCRYSTALHD)
241   if (!hint.software && CSettings::Get().GetBool("videoplayer.usechd"))
242   {
243     if (CCrystalHD::GetInstance()->DevicePresent())
244     {
245       switch(hint.codec)
246       {
247         case AV_CODEC_ID_VC1:
248         case AV_CODEC_ID_WMV3:
249         case AV_CODEC_ID_H264:
250         case AV_CODEC_ID_MPEG2VIDEO:
251           if (hint.codec == AV_CODEC_ID_H264 && hint.ptsinvalid)
252             break;
253           if (hint.codec == AV_CODEC_ID_MPEG2VIDEO && hint.width <= 720)
254             break;
255           if ( (pCodec = OpenCodec(new CDVDVideoCodecCrystalHD(), hint, options)) ) return pCodec;
256         break;
257         default:
258         break;
259       }
260     }
261   }
262 #endif
263
264 #if defined(TARGET_ANDROID)
265   if (!hint.software && CSettings::Get().GetBool("videoplayer.usemediacodec"))
266   {
267     CLog::Log(LOGINFO, "MediaCodec Video Decoder...");
268     if ( (pCodec = OpenCodec(new CDVDVideoCodecAndroidMediaCodec(), hint, options)) ) return pCodec;
269   }
270 #endif
271
272 #if defined(HAVE_LIBOPENMAX)
273   if (CSettings::Get().GetBool("videoplayer.useomx") && !hint.software )
274   {
275       if (hint.codec == AV_CODEC_ID_H264 || hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_VC1)
276     {
277       if ( (pCodec = OpenCodec(new CDVDVideoCodecOpenMax(), hint, options)) ) return pCodec;
278     }
279   }
280 #endif
281
282 #if defined(HAS_LIBSTAGEFRIGHT)
283   if (!hint.software && CSettings::Get().GetBool("videoplayer.usestagefright"))
284   {
285     switch(hint.codec)
286     {
287       case CODEC_ID_H264:
288       case CODEC_ID_MPEG4:
289       case CODEC_ID_MPEG2VIDEO:
290       case CODEC_ID_VC1:
291       case CODEC_ID_WMV3:
292       case CODEC_ID_VP3:
293       case CODEC_ID_VP6:
294       case CODEC_ID_VP6F:
295       case CODEC_ID_VP8:
296         if ( (pCodec = OpenCodec(new CDVDVideoCodecStageFright(), hint, options)) ) return pCodec;
297         break;
298       default:
299         break;
300     }
301   }
302 #endif
303
304   // try to decide if we want to try halfres decoding
305 #if !defined(TARGET_POSIX) && !defined(TARGET_WINDOWS)
306   float pixelrate = (float)hint.width*hint.height*hint.fpsrate/hint.fpsscale;
307   if( pixelrate > 1400.0f*720.0f*30.0f )
308   {
309     CLog::Log(LOGINFO, "CDVDFactoryCodec - High video resolution detected %dx%d, trying half resolution decoding ", hint.width, hint.height);
310     options.m_keys.push_back(CDVDCodecOption("lowres","1"));
311   }
312 #endif
313
314   CStdString value = StringUtils::Format("%d", surfaces);
315   options.m_keys.push_back(CDVDCodecOption("surfaces", value));
316   if( (pCodec = OpenCodec(new CDVDVideoCodecFFmpeg(), hint, options)) ) return pCodec;
317
318   return NULL;
319 }
320
321 CDVDAudioCodec* CDVDFactoryCodec::CreateAudioCodec( CDVDStreamInfo &hint)
322 {
323   CDVDAudioCodec* pCodec = NULL;
324   CDVDCodecOptions options;
325
326   // try passthrough first
327   pCodec = OpenCodec( new CDVDAudioCodecPassthrough(), hint, options );
328   if( pCodec ) return pCodec;
329
330   switch (hint.codec)
331   {
332   case AV_CODEC_ID_MP2:
333   case AV_CODEC_ID_MP3:
334     {
335       pCodec = OpenCodec( new CDVDAudioCodecLibMad(), hint, options );
336       if( pCodec ) return pCodec;
337       break;
338     }
339   case AV_CODEC_ID_PCM_S32LE:
340   case AV_CODEC_ID_PCM_S32BE:
341   case AV_CODEC_ID_PCM_U32LE:
342   case AV_CODEC_ID_PCM_U32BE:
343   case AV_CODEC_ID_PCM_S24LE:
344   case AV_CODEC_ID_PCM_S24BE:
345   case AV_CODEC_ID_PCM_U24LE:
346   case AV_CODEC_ID_PCM_U24BE:
347   case AV_CODEC_ID_PCM_S24DAUD:
348   case AV_CODEC_ID_PCM_S16LE:
349   case AV_CODEC_ID_PCM_S16BE:
350   case AV_CODEC_ID_PCM_U16LE:
351   case AV_CODEC_ID_PCM_U16BE:
352   case AV_CODEC_ID_PCM_S8:
353   case AV_CODEC_ID_PCM_U8:
354   case AV_CODEC_ID_PCM_ALAW:
355   case AV_CODEC_ID_PCM_MULAW:
356     {
357       pCodec = OpenCodec( new CDVDAudioCodecPcm(), hint, options );
358       if( pCodec ) return pCodec;
359       break;
360     }
361 #if 0
362   //case AV_CODEC_ID_LPCM_S16BE:
363   //case AV_CODEC_ID_LPCM_S20BE:
364   case AV_CODEC_ID_LPCM_S24BE:
365     {
366       pCodec = OpenCodec( new CDVDAudioCodecLPcm(), hint, options );
367       if( pCodec ) return pCodec;
368       break;
369     }
370 #endif
371   default:
372     {
373       pCodec = NULL;
374       break;
375     }
376   }
377
378   pCodec = OpenCodec( new CDVDAudioCodecFFmpeg(), hint, options );
379   if( pCodec ) return pCodec;
380
381   return NULL;
382 }
383
384 CDVDOverlayCodec* CDVDFactoryCodec::CreateOverlayCodec( CDVDStreamInfo &hint )
385 {
386   CDVDOverlayCodec* pCodec = NULL;
387   CDVDCodecOptions options;
388
389   switch (hint.codec)
390   {
391     case AV_CODEC_ID_TEXT:
392     case AV_CODEC_ID_SUBRIP:
393       pCodec = OpenCodec(new CDVDOverlayCodecText(), hint, options);
394       if( pCodec ) return pCodec;
395       break;
396
397     case AV_CODEC_ID_SSA:
398       pCodec = OpenCodec(new CDVDOverlayCodecSSA(), hint, options);
399       if( pCodec ) return pCodec;
400
401       pCodec = OpenCodec(new CDVDOverlayCodecText(), hint, options);
402       if( pCodec ) return pCodec;
403       break;
404
405     case AV_CODEC_ID_MOV_TEXT:
406       pCodec = OpenCodec(new CDVDOverlayCodecTX3G(), hint, options);
407       if( pCodec ) return pCodec;
408       break;
409
410     default:
411       pCodec = OpenCodec(new CDVDOverlayCodecFFmpeg(), hint, options);
412       if( pCodec ) return pCodec;
413       break;
414   }
415
416   return NULL;
417 }