[cstdstring] demise Format, replacing with StringUtils::Format
[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 #if defined(TARGET_DARWIN_OSX) || defined(TARGET_DARWIN_IOS)
55 #include "Audio/DVDAudioCodecPassthroughFFmpeg.h"
56 #endif
57 #include "Audio/DVDAudioCodecPassthrough.h"
58 #include "Overlay/DVDOverlayCodecSSA.h"
59 #include "Overlay/DVDOverlayCodecText.h"
60 #include "Overlay/DVDOverlayCodecTX3G.h"
61 #include "Overlay/DVDOverlayCodecFFmpeg.h"
62
63
64 #include "DVDStreamInfo.h"
65 #include "settings/Settings.h"
66 #include "utils/SystemInfo.h"
67 #include "utils/StringUtils.h"
68
69 CDVDVideoCodec* CDVDFactoryCodec::OpenCodec(CDVDVideoCodec* pCodec, CDVDStreamInfo &hints, CDVDCodecOptions &options )
70 {
71   try
72   {
73     CLog::Log(LOGDEBUG, "FactoryCodec - Video: %s - Opening", pCodec->GetName());
74     if( pCodec->Open( hints, options ) )
75     {
76       CLog::Log(LOGDEBUG, "FactoryCodec - Video: %s - Opened", pCodec->GetName());
77       return pCodec;
78     }
79
80     CLog::Log(LOGDEBUG, "FactoryCodec - Video: %s - Failed", pCodec->GetName());
81     pCodec->Dispose();
82     delete pCodec;
83   }
84   catch(...)
85   {
86     CLog::Log(LOGERROR, "FactoryCodec - Video: Failed with exception");
87   }
88   return NULL;
89 }
90
91 CDVDAudioCodec* CDVDFactoryCodec::OpenCodec(CDVDAudioCodec* pCodec, CDVDStreamInfo &hints, CDVDCodecOptions &options )
92 {
93   try
94   {
95     CLog::Log(LOGDEBUG, "FactoryCodec - Audio: %s - Opening", pCodec->GetName());
96     if( pCodec->Open( hints, options ) )
97     {
98       CLog::Log(LOGDEBUG, "FactoryCodec - Audio: %s - Opened", pCodec->GetName());
99       return pCodec;
100     }
101
102     CLog::Log(LOGDEBUG, "FactoryCodec - Audio: %s - Failed", pCodec->GetName());
103     pCodec->Dispose();
104     delete pCodec;
105   }
106   catch(...)
107   {
108     CLog::Log(LOGERROR, "FactoryCodec - Audio: Failed with exception");
109   }
110   return NULL;
111 }
112
113 CDVDOverlayCodec* CDVDFactoryCodec::OpenCodec(CDVDOverlayCodec* pCodec, CDVDStreamInfo &hints, CDVDCodecOptions &options )
114 {
115   try
116   {
117     CLog::Log(LOGDEBUG, "FactoryCodec - Overlay: %s - Opening", pCodec->GetName());
118     if( pCodec->Open( hints, options ) )
119     {
120       CLog::Log(LOGDEBUG, "FactoryCodec - Overlay: %s - Opened", pCodec->GetName());
121       return pCodec;
122     }
123
124     CLog::Log(LOGDEBUG, "FactoryCodec - Overlay: %s - Failed", pCodec->GetName());
125     pCodec->Dispose();
126     delete pCodec;
127   }
128   catch(...)
129   {
130     CLog::Log(LOGERROR, "FactoryCodec - Audio: Failed with exception");
131   }
132   return NULL;
133 }
134
135
136 CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigned int surfaces, const std::vector<ERenderFormat>& formats)
137 {
138   CDVDVideoCodec* pCodec = NULL;
139   CDVDCodecOptions options;
140
141   if(formats.empty())
142     options.m_formats.push_back(RENDER_FMT_YUV420P);
143   else
144     options.m_formats = formats;
145
146   //when support for a hardware decoder is not compiled in
147   //only print it if it's actually available on the platform
148   CStdString hwSupport;
149 #if defined(TARGET_DARWIN_OSX)
150   hwSupport += "VDADecoder:yes ";
151 #endif
152 #if defined(HAVE_VIDEOTOOLBOXDECODER) && defined(TARGET_DARWIN)
153   hwSupport += "VideoToolBoxDecoder:yes ";
154 #elif defined(TARGET_DARWIN)
155   hwSupport += "VideoToolBoxDecoder:no ";
156 #endif
157 #ifdef HAVE_LIBCRYSTALHD
158   hwSupport += "CrystalHD:yes ";
159 #else
160   hwSupport += "CrystalHD:no ";
161 #endif
162 #if defined(HAS_LIBAMCODEC)
163   hwSupport += "AMCodec:yes ";
164 #else
165   hwSupport += "AMCodec:no ";
166 #endif
167 #if defined(TARGET_ANDROID)
168   hwSupport += "MediaCodec:yes ";
169 #else
170   hwSupport += "MediaCodec:no ";
171 #endif
172 #if defined(HAVE_LIBOPENMAX) && defined(TARGET_POSIX)
173   hwSupport += "OpenMax:yes ";
174 #elif defined(TARGET_POSIX)
175   hwSupport += "OpenMax:no ";
176 #endif
177 #if defined(HAS_LIBSTAGEFRIGHT)
178   hwSupport += "libstagefright:yes ";
179 #elif defined(_LINUX)
180   hwSupport += "libstagefright:no ";
181 #endif
182 #if defined(HAVE_LIBVDPAU) && defined(TARGET_POSIX)
183   hwSupport += "VDPAU:yes ";
184 #elif defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
185   hwSupport += "VDPAU:no ";
186 #endif
187 #if defined(TARGET_WINDOWS) && defined(HAS_DX)
188   hwSupport += "DXVA:yes ";
189 #elif defined(TARGET_WINDOWS)
190   hwSupport += "DXVA:no ";
191 #endif
192 #if defined(HAVE_LIBVA) && defined(TARGET_POSIX)
193   hwSupport += "VAAPI:yes ";
194 #elif defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
195   hwSupport += "VAAPI:no ";
196 #endif
197
198   CLog::Log(LOGDEBUG, "CDVDFactoryCodec: compiled in hardware support: %s", hwSupport.c_str());
199 #if defined(HAS_LIBAMCODEC)
200   // amcodec can handle dvd playback.
201   if (!CSettings::Get().GetBool("videoplayer.useamcodec"))
202 #endif
203   {
204     // dvd's have weird still-frames in it, which is not fully supported in ffmpeg
205     if(hint.stills && (hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_MPEG1VIDEO))
206     {
207       if( (pCodec = OpenCodec(new CDVDVideoCodecLibMpeg2(), hint, options)) ) return pCodec;
208     }
209   }
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(HAS_LIBAMCODEC)
265   if (!hint.software && CSettings::Get().GetBool("videoplayer.useamcodec"))
266   {
267     CLog::Log(LOGINFO, "Amlogic Video Decoder...");
268     if ( (pCodec = OpenCodec(new CDVDVideoCodecAmlogic(), hint, options)) ) return pCodec;
269   }
270 #endif
271
272 #if defined(TARGET_ANDROID)
273   if (!hint.software && CSettings::Get().GetBool("videoplayer.usemediacodec"))
274   {
275     CLog::Log(LOGINFO, "MediaCodec Video Decoder...");
276     if ( (pCodec = OpenCodec(new CDVDVideoCodecAndroidMediaCodec(), hint, options)) ) return pCodec;
277   }
278 #endif
279
280 #if defined(HAVE_LIBOPENMAX)
281   if (CSettings::Get().GetBool("videoplayer.useomx") && !hint.software )
282   {
283       if (hint.codec == AV_CODEC_ID_H264 || hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_VC1)
284     {
285       if ( (pCodec = OpenCodec(new CDVDVideoCodecOpenMax(), hint, options)) ) return pCodec;
286     }
287   }
288 #endif
289
290 #if defined(HAS_LIBSTAGEFRIGHT)
291   if (!hint.software && CSettings::Get().GetBool("videoplayer.usestagefright"))
292   {
293     switch(hint.codec)
294     {
295       case CODEC_ID_H264:
296       case CODEC_ID_MPEG4:
297       case CODEC_ID_MPEG2VIDEO:
298       case CODEC_ID_VC1:
299       case CODEC_ID_WMV3:
300       case CODEC_ID_VP3:
301       case CODEC_ID_VP6:
302       case CODEC_ID_VP6F:
303       case CODEC_ID_VP8:
304         if ( (pCodec = OpenCodec(new CDVDVideoCodecStageFright(), hint, options)) ) return pCodec;
305         break;
306       default:
307         break;
308     }
309   }
310 #endif
311
312   // try to decide if we want to try halfres decoding
313 #if !defined(TARGET_POSIX) && !defined(TARGET_WINDOWS)
314   float pixelrate = (float)hint.width*hint.height*hint.fpsrate/hint.fpsscale;
315   if( pixelrate > 1400.0f*720.0f*30.0f )
316   {
317     CLog::Log(LOGINFO, "CDVDFactoryCodec - High video resolution detected %dx%d, trying half resolution decoding ", hint.width, hint.height);
318     options.m_keys.push_back(CDVDCodecOption("lowres","1"));
319   }
320 #endif
321
322   CStdString value = StringUtils::Format("%d", surfaces);
323   options.m_keys.push_back(CDVDCodecOption("surfaces", value));
324   if( (pCodec = OpenCodec(new CDVDVideoCodecFFmpeg(), hint, options)) ) return pCodec;
325
326   return NULL;
327 }
328
329 CDVDAudioCodec* CDVDFactoryCodec::CreateAudioCodec( CDVDStreamInfo &hint)
330 {
331   CDVDAudioCodec* pCodec = NULL;
332   CDVDCodecOptions options;
333
334   // try passthrough first
335 #if defined(TARGET_DARWIN_OSX) || defined(TARGET_DARWIN_IOS)
336   switch(hint.codec)
337   {
338     case AV_CODEC_ID_AC3:
339     case AV_CODEC_ID_DTS:
340       pCodec = OpenCodec( new CDVDAudioCodecPassthroughFFmpeg(), hint, options );
341       if( pCodec ) return pCodec;
342       break;
343     default:
344       break;
345   }
346 #endif
347   pCodec = OpenCodec( new CDVDAudioCodecPassthrough(), hint, options );
348   if( pCodec ) return pCodec;
349
350   switch (hint.codec)
351   {
352   case AV_CODEC_ID_MP2:
353   case AV_CODEC_ID_MP3:
354     {
355       pCodec = OpenCodec( new CDVDAudioCodecLibMad(), hint, options );
356       if( pCodec ) return pCodec;
357       break;
358     }
359   case AV_CODEC_ID_PCM_S32LE:
360   case AV_CODEC_ID_PCM_S32BE:
361   case AV_CODEC_ID_PCM_U32LE:
362   case AV_CODEC_ID_PCM_U32BE:
363   case AV_CODEC_ID_PCM_S24LE:
364   case AV_CODEC_ID_PCM_S24BE:
365   case AV_CODEC_ID_PCM_U24LE:
366   case AV_CODEC_ID_PCM_U24BE:
367   case AV_CODEC_ID_PCM_S24DAUD:
368   case AV_CODEC_ID_PCM_S16LE:
369   case AV_CODEC_ID_PCM_S16BE:
370   case AV_CODEC_ID_PCM_U16LE:
371   case AV_CODEC_ID_PCM_U16BE:
372   case AV_CODEC_ID_PCM_S8:
373   case AV_CODEC_ID_PCM_U8:
374   case AV_CODEC_ID_PCM_ALAW:
375   case AV_CODEC_ID_PCM_MULAW:
376     {
377       pCodec = OpenCodec( new CDVDAudioCodecPcm(), hint, options );
378       if( pCodec ) return pCodec;
379       break;
380     }
381 #if 0
382   //case AV_CODEC_ID_LPCM_S16BE:
383   //case AV_CODEC_ID_LPCM_S20BE:
384   case AV_CODEC_ID_LPCM_S24BE:
385     {
386       pCodec = OpenCodec( new CDVDAudioCodecLPcm(), hint, options );
387       if( pCodec ) return pCodec;
388       break;
389     }
390 #endif
391   default:
392     {
393       pCodec = NULL;
394       break;
395     }
396   }
397
398   pCodec = OpenCodec( new CDVDAudioCodecFFmpeg(), hint, options );
399   if( pCodec ) return pCodec;
400
401   return NULL;
402 }
403
404 CDVDOverlayCodec* CDVDFactoryCodec::CreateOverlayCodec( CDVDStreamInfo &hint )
405 {
406   CDVDOverlayCodec* pCodec = NULL;
407   CDVDCodecOptions options;
408
409   switch (hint.codec)
410   {
411     case AV_CODEC_ID_TEXT:
412     case AV_CODEC_ID_SUBRIP:
413       pCodec = OpenCodec(new CDVDOverlayCodecText(), hint, options);
414       if( pCodec ) return pCodec;
415       break;
416
417     case AV_CODEC_ID_SSA:
418       pCodec = OpenCodec(new CDVDOverlayCodecSSA(), hint, options);
419       if( pCodec ) return pCodec;
420
421       pCodec = OpenCodec(new CDVDOverlayCodecText(), hint, options);
422       if( pCodec ) return pCodec;
423       break;
424
425     case AV_CODEC_ID_MOV_TEXT:
426       pCodec = OpenCodec(new CDVDOverlayCodecTX3G(), hint, options);
427       if( pCodec ) return pCodec;
428       break;
429
430     default:
431       pCodec = OpenCodec(new CDVDOverlayCodecFFmpeg(), hint, options);
432       if( pCodec ) return pCodec;
433       break;
434   }
435
436   return NULL;
437 }