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 #include "Audio/DVDAudioCodecPassthrough.h"
55 #include "Overlay/DVDOverlayCodecSSA.h"
56 #include "Overlay/DVDOverlayCodecText.h"
57 #include "Overlay/DVDOverlayCodecTX3G.h"
58 #include "Overlay/DVDOverlayCodecFFmpeg.h"
61 #include "DVDStreamInfo.h"
62 #include "settings/Settings.h"
63 #include "utils/SystemInfo.h"
64 #include "utils/StringUtils.h"
66 CDVDVideoCodec* CDVDFactoryCodec::OpenCodec(CDVDVideoCodec* pCodec, CDVDStreamInfo &hints, CDVDCodecOptions &options )
70 CLog::Log(LOGDEBUG, "FactoryCodec - Video: %s - Opening", pCodec->GetName());
71 if( pCodec->Open( hints, options ) )
73 CLog::Log(LOGDEBUG, "FactoryCodec - Video: %s - Opened", pCodec->GetName());
77 CLog::Log(LOGDEBUG, "FactoryCodec - Video: %s - Failed", pCodec->GetName());
83 CLog::Log(LOGERROR, "FactoryCodec - Video: Failed with exception");
88 CDVDAudioCodec* CDVDFactoryCodec::OpenCodec(CDVDAudioCodec* pCodec, CDVDStreamInfo &hints, CDVDCodecOptions &options )
92 CLog::Log(LOGDEBUG, "FactoryCodec - Audio: %s - Opening", pCodec->GetName());
93 if( pCodec->Open( hints, options ) )
95 CLog::Log(LOGDEBUG, "FactoryCodec - Audio: %s - Opened", pCodec->GetName());
99 CLog::Log(LOGDEBUG, "FactoryCodec - Audio: %s - Failed", pCodec->GetName());
105 CLog::Log(LOGERROR, "FactoryCodec - Audio: Failed with exception");
110 CDVDOverlayCodec* CDVDFactoryCodec::OpenCodec(CDVDOverlayCodec* pCodec, CDVDStreamInfo &hints, CDVDCodecOptions &options )
114 CLog::Log(LOGDEBUG, "FactoryCodec - Overlay: %s - Opening", pCodec->GetName());
115 if( pCodec->Open( hints, options ) )
117 CLog::Log(LOGDEBUG, "FactoryCodec - Overlay: %s - Opened", pCodec->GetName());
121 CLog::Log(LOGDEBUG, "FactoryCodec - Overlay: %s - Failed", pCodec->GetName());
127 CLog::Log(LOGERROR, "FactoryCodec - Audio: Failed with exception");
133 CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigned int surfaces, const std::vector<ERenderFormat>& formats)
135 CDVDVideoCodec* pCodec = NULL;
136 CDVDCodecOptions options;
139 options.m_formats.push_back(RENDER_FMT_YUV420P);
141 options.m_formats = formats;
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 ";
149 #if defined(HAVE_VIDEOTOOLBOXDECODER) && defined(TARGET_DARWIN)
150 hwSupport += "VideoToolBoxDecoder:yes ";
151 #elif defined(TARGET_DARWIN)
152 hwSupport += "VideoToolBoxDecoder:no ";
154 #ifdef HAVE_LIBCRYSTALHD
155 hwSupport += "CrystalHD:yes ";
157 hwSupport += "CrystalHD:no ";
159 #if defined(HAS_LIBAMCODEC)
160 hwSupport += "AMCodec:yes ";
162 hwSupport += "AMCodec:no ";
164 #if defined(TARGET_ANDROID)
165 hwSupport += "MediaCodec:yes ";
167 hwSupport += "MediaCodec:no ";
169 #if defined(HAVE_LIBOPENMAX) && defined(TARGET_POSIX)
170 hwSupport += "OpenMax:yes ";
171 #elif defined(TARGET_POSIX)
172 hwSupport += "OpenMax:no ";
174 #if defined(HAS_LIBSTAGEFRIGHT)
175 hwSupport += "libstagefright:yes ";
176 #elif defined(_LINUX)
177 hwSupport += "libstagefright:no ";
179 #if defined(HAVE_LIBVDPAU) && defined(TARGET_POSIX)
180 hwSupport += "VDPAU:yes ";
181 #elif defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
182 hwSupport += "VDPAU:no ";
184 #if defined(TARGET_WINDOWS) && defined(HAS_DX)
185 hwSupport += "DXVA:yes ";
186 #elif defined(TARGET_WINDOWS)
187 hwSupport += "DXVA:no ";
189 #if defined(HAVE_LIBVA) && defined(TARGET_POSIX)
190 hwSupport += "VAAPI:yes ";
191 #elif defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
192 hwSupport += "VAAPI:no ";
195 CLog::Log(LOGDEBUG, "CDVDFactoryCodec: compiled in hardware support: %s", hwSupport.c_str());
197 if (hint.stills && (hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_MPEG1VIDEO))
199 // If dvd is an mpeg2 and hint.stills
200 if ( (pCodec = OpenCodec(new CDVDVideoCodecLibMpeg2(), hint, options)) ) return pCodec;
203 #if defined(HAS_LIBAMCODEC)
204 // amcodec can handle dvd playback.
205 if (!hint.software && CSettings::Get().GetBool("videoplayer.useamcodec"))
207 if ( (pCodec = OpenCodec(new CDVDVideoCodecAmlogic(), 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(TARGET_ANDROID)
265 if (!hint.software && CSettings::Get().GetBool("videoplayer.usemediacodec"))
267 CLog::Log(LOGINFO, "MediaCodec Video Decoder...");
268 if ( (pCodec = OpenCodec(new CDVDVideoCodecAndroidMediaCodec(), hint, options)) ) return pCodec;
272 #if defined(HAVE_LIBOPENMAX)
273 if (CSettings::Get().GetBool("videoplayer.useomx") && !hint.software )
275 if (hint.codec == AV_CODEC_ID_H264 || hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_VC1)
277 if ( (pCodec = OpenCodec(new CDVDVideoCodecOpenMax(), hint, options)) ) return pCodec;
282 #if defined(HAS_LIBSTAGEFRIGHT)
283 if (!hint.software && CSettings::Get().GetBool("videoplayer.usestagefright"))
289 case CODEC_ID_MPEG2VIDEO:
296 if ( (pCodec = OpenCodec(new CDVDVideoCodecStageFright(), hint, options)) ) return pCodec;
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 )
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"));
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;
321 CDVDAudioCodec* CDVDFactoryCodec::CreateAudioCodec( CDVDStreamInfo &hint)
323 CDVDAudioCodec* pCodec = NULL;
324 CDVDCodecOptions options;
326 // try passthrough first
327 pCodec = OpenCodec( new CDVDAudioCodecPassthrough(), hint, options );
328 if( pCodec ) return pCodec;
332 case AV_CODEC_ID_MP2:
333 case AV_CODEC_ID_MP3:
335 pCodec = OpenCodec( new CDVDAudioCodecLibMad(), hint, options );
336 if( pCodec ) return pCodec;
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:
357 pCodec = OpenCodec( new CDVDAudioCodecPcm(), hint, options );
358 if( pCodec ) return pCodec;
362 //case AV_CODEC_ID_LPCM_S16BE:
363 //case AV_CODEC_ID_LPCM_S20BE:
364 case AV_CODEC_ID_LPCM_S24BE:
366 pCodec = OpenCodec( new CDVDAudioCodecLPcm(), hint, options );
367 if( pCodec ) return pCodec;
378 pCodec = OpenCodec( new CDVDAudioCodecFFmpeg(), hint, options );
379 if( pCodec ) return pCodec;
384 CDVDOverlayCodec* CDVDFactoryCodec::CreateOverlayCodec( CDVDStreamInfo &hint )
386 CDVDOverlayCodec* pCodec = NULL;
387 CDVDCodecOptions options;
391 case AV_CODEC_ID_TEXT:
392 case AV_CODEC_ID_SUBRIP:
393 pCodec = OpenCodec(new CDVDOverlayCodecText(), hint, options);
394 if( pCodec ) return pCodec;
397 case AV_CODEC_ID_SSA:
398 pCodec = OpenCodec(new CDVDOverlayCodecSSA(), hint, options);
399 if( pCodec ) return pCodec;
401 pCodec = OpenCodec(new CDVDOverlayCodecText(), hint, options);
402 if( pCodec ) return pCodec;
405 case AV_CODEC_ID_MOV_TEXT:
406 pCodec = OpenCodec(new CDVDOverlayCodecTX3G(), hint, options);
407 if( pCodec ) return pCodec;
411 pCodec = OpenCodec(new CDVDOverlayCodecFFmpeg(), hint, options);
412 if( pCodec ) return pCodec;