2 * Copyright (C) 2005-2013 Team XBMC
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)
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.
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/>.
22 #include "utils/log.h"
24 #include "DVDFactoryCodec.h"
25 #include "Video/DVDVideoCodec.h"
26 #include "Audio/DVDAudioCodec.h"
27 #include "Overlay/DVDOverlayCodec.h"
29 #if defined(TARGET_DARWIN_OSX)
30 #include "Video/DVDVideoCodecVDA.h"
32 #if defined(HAVE_VIDEOTOOLBOXDECODER)
33 #include "Video/DVDVideoCodecVideoToolBox.h"
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"
42 #if defined(HAS_LIBAMCODEC)
43 #include "utils/AMLUtils.h"
44 #include "Video/DVDVideoCodecAmlogic.h"
46 #if defined(TARGET_ANDROID)
47 #include "Video/DVDVideoCodecAndroidMediaCodec.h"
48 #include "android/activity/AndroidFeatures.h"
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"
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"
64 #include "DVDStreamInfo.h"
65 #include "settings/Settings.h"
66 #include "utils/SystemInfo.h"
67 #include "utils/StringUtils.h"
69 CDVDVideoCodec* CDVDFactoryCodec::OpenCodec(CDVDVideoCodec* pCodec, CDVDStreamInfo &hints, CDVDCodecOptions &options )
73 CLog::Log(LOGDEBUG, "FactoryCodec - Video: %s - Opening", pCodec->GetName());
74 if( pCodec->Open( hints, options ) )
76 CLog::Log(LOGDEBUG, "FactoryCodec - Video: %s - Opened", pCodec->GetName());
80 CLog::Log(LOGDEBUG, "FactoryCodec - Video: %s - Failed", pCodec->GetName());
86 CLog::Log(LOGERROR, "FactoryCodec - Video: Failed with exception");
91 CDVDAudioCodec* CDVDFactoryCodec::OpenCodec(CDVDAudioCodec* pCodec, CDVDStreamInfo &hints, CDVDCodecOptions &options )
95 CLog::Log(LOGDEBUG, "FactoryCodec - Audio: %s - Opening", pCodec->GetName());
96 if( pCodec->Open( hints, options ) )
98 CLog::Log(LOGDEBUG, "FactoryCodec - Audio: %s - Opened", pCodec->GetName());
102 CLog::Log(LOGDEBUG, "FactoryCodec - Audio: %s - Failed", pCodec->GetName());
108 CLog::Log(LOGERROR, "FactoryCodec - Audio: Failed with exception");
113 CDVDOverlayCodec* CDVDFactoryCodec::OpenCodec(CDVDOverlayCodec* pCodec, CDVDStreamInfo &hints, CDVDCodecOptions &options )
117 CLog::Log(LOGDEBUG, "FactoryCodec - Overlay: %s - Opening", pCodec->GetName());
118 if( pCodec->Open( hints, options ) )
120 CLog::Log(LOGDEBUG, "FactoryCodec - Overlay: %s - Opened", pCodec->GetName());
124 CLog::Log(LOGDEBUG, "FactoryCodec - Overlay: %s - Failed", pCodec->GetName());
130 CLog::Log(LOGERROR, "FactoryCodec - Audio: Failed with exception");
136 CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigned int surfaces, const std::vector<ERenderFormat>& formats)
138 CDVDVideoCodec* pCodec = NULL;
139 CDVDCodecOptions options;
142 options.m_formats.push_back(RENDER_FMT_YUV420P);
144 options.m_formats = formats;
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 ";
152 #if defined(HAVE_VIDEOTOOLBOXDECODER) && defined(TARGET_DARWIN)
153 hwSupport += "VideoToolBoxDecoder:yes ";
154 #elif defined(TARGET_DARWIN)
155 hwSupport += "VideoToolBoxDecoder:no ";
157 #ifdef HAVE_LIBCRYSTALHD
158 hwSupport += "CrystalHD:yes ";
160 hwSupport += "CrystalHD:no ";
162 #if defined(HAS_LIBAMCODEC)
163 hwSupport += "AMCodec:yes ";
165 hwSupport += "AMCodec:no ";
167 #if defined(TARGET_ANDROID)
168 hwSupport += "MediaCodec:yes ";
170 hwSupport += "MediaCodec:no ";
172 #if defined(HAVE_LIBOPENMAX) && defined(TARGET_POSIX)
173 hwSupport += "OpenMax:yes ";
174 #elif defined(TARGET_POSIX)
175 hwSupport += "OpenMax:no ";
177 #if defined(HAS_LIBSTAGEFRIGHT)
178 hwSupport += "libstagefright:yes ";
179 #elif defined(_LINUX)
180 hwSupport += "libstagefright:no ";
182 #if defined(HAVE_LIBVDPAU) && defined(TARGET_POSIX)
183 hwSupport += "VDPAU:yes ";
184 #elif defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
185 hwSupport += "VDPAU:no ";
187 #if defined(TARGET_WINDOWS) && defined(HAS_DX)
188 hwSupport += "DXVA:yes ";
189 #elif defined(TARGET_WINDOWS)
190 hwSupport += "DXVA:no ";
192 #if defined(HAVE_LIBVA) && defined(TARGET_POSIX)
193 hwSupport += "VAAPI:yes ";
194 #elif defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
195 hwSupport += "VAAPI:no ";
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"))
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))
207 if( (pCodec = OpenCodec(new CDVDVideoCodecLibMpeg2(), hint, options)) ) return pCodec;
211 #if defined(TARGET_DARWIN_OSX)
212 if (!hint.software && CSettings::Get().GetBool("videoplayer.usevda"))
214 if (hint.codec == AV_CODEC_ID_H264 && !hint.ptsinvalid)
216 if ( (pCodec = OpenCodec(new CDVDVideoCodecVDA(), hint, options)) ) return pCodec;
221 #if defined(HAVE_VIDEOTOOLBOXDECODER)
222 if (!hint.software && CSettings::Get().GetBool("videoplayer.usevideotoolbox"))
224 if (g_sysinfo.HasVideoToolBoxDecoder())
228 case AV_CODEC_ID_H264:
229 if (hint.codec == AV_CODEC_ID_H264 && hint.ptsinvalid)
231 if ( (pCodec = OpenCodec(new CDVDVideoCodecVideoToolBox(), hint, options)) ) return pCodec;
240 #if defined(HAVE_LIBCRYSTALHD)
241 if (!hint.software && CSettings::Get().GetBool("videoplayer.usechd"))
243 if (CCrystalHD::GetInstance()->DevicePresent())
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)
253 if (hint.codec == AV_CODEC_ID_MPEG2VIDEO && hint.width <= 720)
255 if ( (pCodec = OpenCodec(new CDVDVideoCodecCrystalHD(), hint, options)) ) return pCodec;
264 #if defined(HAS_LIBAMCODEC)
265 if (!hint.software && CSettings::Get().GetBool("videoplayer.useamcodec"))
267 CLog::Log(LOGINFO, "Amlogic Video Decoder...");
268 if ( (pCodec = OpenCodec(new CDVDVideoCodecAmlogic(), hint, options)) ) return pCodec;
272 #if defined(TARGET_ANDROID)
273 if (!hint.software && CSettings::Get().GetBool("videoplayer.usemediacodec"))
275 CLog::Log(LOGINFO, "MediaCodec Video Decoder...");
276 if ( (pCodec = OpenCodec(new CDVDVideoCodecAndroidMediaCodec(), hint, options)) ) return pCodec;
280 #if defined(HAVE_LIBOPENMAX)
281 if (CSettings::Get().GetBool("videoplayer.useomx") && !hint.software )
283 if (hint.codec == AV_CODEC_ID_H264 || hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_VC1)
285 if ( (pCodec = OpenCodec(new CDVDVideoCodecOpenMax(), hint, options)) ) return pCodec;
290 #if defined(HAS_LIBSTAGEFRIGHT)
291 if (!hint.software && CSettings::Get().GetBool("videoplayer.usestagefright"))
297 case CODEC_ID_MPEG2VIDEO:
304 if ( (pCodec = OpenCodec(new CDVDVideoCodecStageFright(), hint, options)) ) return pCodec;
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 )
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"));
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;
329 CDVDAudioCodec* CDVDFactoryCodec::CreateAudioCodec( CDVDStreamInfo &hint)
331 CDVDAudioCodec* pCodec = NULL;
332 CDVDCodecOptions options;
334 // try passthrough first
335 #if defined(TARGET_DARWIN_OSX) || defined(TARGET_DARWIN_IOS)
338 case AV_CODEC_ID_AC3:
339 case AV_CODEC_ID_DTS:
340 pCodec = OpenCodec( new CDVDAudioCodecPassthroughFFmpeg(), hint, options );
341 if( pCodec ) return pCodec;
347 pCodec = OpenCodec( new CDVDAudioCodecPassthrough(), hint, options );
348 if( pCodec ) return pCodec;
352 case AV_CODEC_ID_MP2:
353 case AV_CODEC_ID_MP3:
355 pCodec = OpenCodec( new CDVDAudioCodecLibMad(), hint, options );
356 if( pCodec ) return pCodec;
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:
377 pCodec = OpenCodec( new CDVDAudioCodecPcm(), hint, options );
378 if( pCodec ) return pCodec;
382 //case AV_CODEC_ID_LPCM_S16BE:
383 //case AV_CODEC_ID_LPCM_S20BE:
384 case AV_CODEC_ID_LPCM_S24BE:
386 pCodec = OpenCodec( new CDVDAudioCodecLPcm(), hint, options );
387 if( pCodec ) return pCodec;
398 pCodec = OpenCodec( new CDVDAudioCodecFFmpeg(), hint, options );
399 if( pCodec ) return pCodec;
404 CDVDOverlayCodec* CDVDFactoryCodec::CreateOverlayCodec( CDVDStreamInfo &hint )
406 CDVDOverlayCodec* pCodec = NULL;
407 CDVDCodecOptions options;
411 case AV_CODEC_ID_TEXT:
412 case AV_CODEC_ID_SUBRIP:
413 pCodec = OpenCodec(new CDVDOverlayCodecText(), hint, options);
414 if( pCodec ) return pCodec;
417 case AV_CODEC_ID_SSA:
418 pCodec = OpenCodec(new CDVDOverlayCodecSSA(), hint, options);
419 if( pCodec ) return pCodec;
421 pCodec = OpenCodec(new CDVDOverlayCodecText(), hint, options);
422 if( pCodec ) return pCodec;
425 case AV_CODEC_ID_MOV_TEXT:
426 pCodec = OpenCodec(new CDVDOverlayCodecTX3G(), hint, options);
427 if( pCodec ) return pCodec;
431 pCodec = OpenCodec(new CDVDOverlayCodecFFmpeg(), hint, options);
432 if( pCodec ) return pCodec;