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/>.
21 #include "DVDPlayerCodec.h"
22 #include "cores/AudioEngine/Utils/AEUtil.h"
24 #include "cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.h"
25 #include "cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.h"
26 #include "cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.h"
27 #include "cores/dvdplayer/DVDStreamInfo.h"
28 #include "cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h"
29 #include "music/tags/TagLoaderTagLib.h"
30 #include "utils/log.h"
31 #include "settings/Settings.h"
34 #include "AudioDecoder.h"
36 DVDPlayerCodec::DVDPlayerCodec()
38 m_CodecName
= "DVDPlayer";
40 m_pInputStream
= NULL
;
51 DVDPlayerCodec::~DVDPlayerCodec()
56 void DVDPlayerCodec::SetContentType(const CStdString
&strContent
)
58 m_strContentType
= strContent
;
61 bool DVDPlayerCodec::Init(const CStdString
&strFile
, unsigned int filecache
)
63 // take precaution if Init()ialized earlier
66 // keep things as is if Init() was done with known strFile
67 if (m_strFileName
== strFile
)
70 // got differing filename, so cleanup before starting over
77 CStdString strFileToOpen
= strFile
;
79 CURL
urlFile(strFile
);
80 if (urlFile
.GetProtocol() == "shout" )
81 strFileToOpen
.replace(0, 8, "http://");
83 m_pInputStream
= CDVDFactoryInputStream::CreateInputStream(NULL
, strFileToOpen
, m_strContentType
);
86 CLog::Log(LOGERROR
, "%s: Error creating input stream for %s", __FUNCTION__
, strFileToOpen
.c_str());
90 if (!m_pInputStream
->Open(strFileToOpen
.c_str(), m_strContentType
))
92 CLog::Log(LOGERROR
, "%s: Error opening file %s", __FUNCTION__
, strFileToOpen
.c_str());
94 delete m_pInputStream
;
95 m_pInputStream
= NULL
;
103 m_pDemuxer
= CDVDFactoryDemuxer::CreateDemuxer(m_pInputStream
);
106 delete m_pInputStream
;
107 m_pInputStream
= NULL
;
108 CLog::Log(LOGERROR
, "%s: Error creating demuxer", __FUNCTION__
);
114 CLog::Log(LOGERROR
, "%s: Exception thrown when opening demuxer", __FUNCTION__
);
120 delete m_pInputStream
;
121 m_pInputStream
= NULL
;
125 CDemuxStream
* pStream
= NULL
;
127 for (int i
= 0; i
< m_pDemuxer
->GetNrOfStreams(); i
++)
129 pStream
= m_pDemuxer
->GetStream(i
);
130 if (pStream
&& pStream
->type
== STREAM_AUDIO
)
137 if (m_nAudioStream
== -1)
139 CLog::Log(LOGERROR
, "%s: Could not find audio stream", __FUNCTION__
);
142 delete m_pInputStream
;
143 m_pInputStream
= NULL
;
147 CDVDStreamInfo
hint(*pStream
, true);
149 m_pAudioCodec
= CDVDFactoryCodec::CreateAudioCodec(hint
);
152 CLog::Log(LOGERROR
, "%s: Could not create audio codec", __FUNCTION__
);
155 delete m_pInputStream
;
156 m_pInputStream
= NULL
;
160 // Extract ReplayGain info
161 // tagLoaderTagLib.Load will try to determine tag type by file extension, so set fallback by contentType
162 CStdString strFallbackFileExtension
= "";
163 if (m_strContentType
.Equals("audio/aacp") || m_strContentType
.Equals("audio/aacp" "audio/aac"))
164 strFallbackFileExtension
= "m4a";
165 else if (m_strContentType
.Equals("audio/x-ms-wma"))
166 strFallbackFileExtension
= "wma";
167 else if (m_strContentType
.Equals("audio/x-ape") || m_strContentType
.Equals("audio/ape"))
168 strFallbackFileExtension
= "ape";
169 CTagLoaderTagLib tagLoaderTagLib
;
170 tagLoaderTagLib
.Load(strFile
, m_tag
, strFallbackFileExtension
);
172 // we have to decode initial data in order to get channels/samplerate
173 // for sanity - we read no more than 10 packets
175 for (int nPacket
=0; nPacket
< 10 && (m_Channels
== 0 || m_SampleRate
== 0); nPacket
++)
179 if (ReadPCM(dummy
, nSize
, &nSize
) == READ_ERROR
)
182 m_DataFormat
= m_pAudioCodec
->GetDataFormat();
183 m_BitsPerSample
= CAEUtil::DataFormatToBits(m_DataFormat
);
184 m_SampleRate
= m_pAudioCodec
->GetSampleRate();
185 m_EncodedSampleRate
= m_pAudioCodec
->GetEncodedSampleRate();
186 m_Channels
= m_pAudioCodec
->GetChannels();
187 m_ChannelInfo
= m_pAudioCodec
->GetChannelMap();
188 m_BitsPerCodedSample
= static_cast<CDemuxStreamAudio
*>(pStream
)->iBitsPerSample
;
192 CLog::Log(LOGDEBUG
, "%s: Could not decode data", __FUNCTION__
);
196 // test if seeking is supported
197 if (Seek(1) != DVD_NOPTS_VALUE
)
199 // rewind stream to beginning
205 m_pInputStream
->Seek(0, SEEK_SET
);
210 if (m_Channels
== 0) // no data - just guess and hope for the best
213 if (m_SampleRate
== 0)
214 m_SampleRate
= 44100;
216 m_TotalTime
= m_pDemuxer
->GetStreamLength();
217 m_Bitrate
= m_pAudioCodec
->GetBitRate();
218 if (!m_Bitrate
&& m_TotalTime
)
220 m_Bitrate
= (int)(((m_pInputStream
->GetLength()*1000) / m_TotalTime
) * 8);
222 m_pDemuxer
->GetStreamCodecName(m_nAudioStream
,m_CodecName
);
224 m_strFileName
= strFile
;
230 void DVDPlayerCodec::DeInit()
233 CDVDDemuxUtils::FreeDemuxPacket(m_pPacket
);
236 if (m_pDemuxer
!= NULL
)
242 if (m_pInputStream
!= NULL
)
244 delete m_pInputStream
;
245 m_pInputStream
= NULL
;
248 if (m_pAudioCodec
!= NULL
)
250 delete m_pAudioCodec
;
251 m_pAudioCodec
= NULL
;
254 // cleanup format information
257 m_EncodedSampleRate
= 0;
259 m_DataFormat
= AE_FMT_INVALID
;
271 int64_t DVDPlayerCodec::Seek(int64_t iSeekTime
)
274 CDVDDemuxUtils::FreeDemuxPacket(m_pPacket
);
277 bool ret
= m_pDemuxer
->SeekTime((int)iSeekTime
, false);
278 m_pAudioCodec
->Reset();
284 return DVD_NOPTS_VALUE
;
289 int DVDPlayerCodec::ReadPCM(BYTE
*pBuffer
, int size
, int *actualsize
)
291 if (m_decoded
&& m_nDecodedLen
> 0)
293 int nLen
= (size
<m_nDecodedLen
)?size
:m_nDecodedLen
;
295 memcpy(pBuffer
, m_decoded
, *actualsize
);
296 m_nDecodedLen
-= nLen
;
297 m_decoded
+= (*actualsize
);
304 // dvdplayer returns a read error on a single invalid packet, while
305 // in paplayer READ_ERROR is a fatal error.
306 // Therefore skip over invalid packets here.
308 for (int tries
= 0; decodeLen
< 0 && tries
< 2; ++tries
)
310 if (m_pPacket
&& m_audioPos
>= m_pPacket
->iSize
)
312 CDVDDemuxUtils::FreeDemuxPacket(m_pPacket
);
317 if (m_pPacket
== NULL
)
321 m_pPacket
= m_pDemuxer
->Read();
322 } while (m_pPacket
&& m_pPacket
->iStreamId
!= m_nAudioStream
);
331 decodeLen
= m_pAudioCodec
->Decode(m_pPacket
->pData
+ m_audioPos
, m_pPacket
->iSize
- m_audioPos
);
334 m_audioPos
= m_pPacket
->iSize
; // skip packet
339 CDVDDemuxUtils::FreeDemuxPacket(m_pPacket
);
345 m_audioPos
+= decodeLen
;
347 m_nDecodedLen
= m_pAudioCodec
->GetData(&m_decoded
);
349 *actualsize
= (m_nDecodedLen
<= size
) ? m_nDecodedLen
: size
;
352 memcpy(pBuffer
, m_decoded
, *actualsize
);
353 m_nDecodedLen
-= *actualsize
;
354 m_decoded
+= (*actualsize
);
360 bool DVDPlayerCodec::CanInit()
365 bool DVDPlayerCodec::CanSeek()