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 "utils/log.h"
30 #include "settings/Settings.h"
33 #include "AudioDecoder.h"
35 DVDPlayerCodec::DVDPlayerCodec()
37 m_CodecName = "DVDPlayer";
39 m_pInputStream = NULL;
50 DVDPlayerCodec::~DVDPlayerCodec()
55 void DVDPlayerCodec::SetContentType(const CStdString &strContent)
57 m_strContentType = strContent;
60 bool DVDPlayerCodec::Init(const CStdString &strFile, unsigned int filecache)
62 // take precaution if Init()ialized earlier
65 // keep things as is if Init() was done with known strFile
66 if (m_strFileName == strFile)
69 // got differing filename, so cleanup before starting over
76 CStdString strFileToOpen = strFile;
78 CURL urlFile(strFile);
79 if (urlFile.GetProtocol() == "shout" )
80 strFileToOpen.Replace("shout://","http://");
82 m_pInputStream = CDVDFactoryInputStream::CreateInputStream(NULL, strFileToOpen, m_strContentType);
85 CLog::Log(LOGERROR, "%s: Error creating input stream for %s", __FUNCTION__, strFileToOpen.c_str());
89 if (!m_pInputStream->Open(strFileToOpen.c_str(), m_strContentType))
91 CLog::Log(LOGERROR, "%s: Error opening file %s", __FUNCTION__, strFileToOpen.c_str());
93 delete m_pInputStream;
94 m_pInputStream = NULL;
102 m_pDemuxer = CDVDFactoryDemuxer::CreateDemuxer(m_pInputStream);
105 delete m_pInputStream;
106 m_pInputStream = NULL;
107 CLog::Log(LOGERROR, "%s: Error creating demuxer", __FUNCTION__);
113 CLog::Log(LOGERROR, "%s: Exception thrown when opening demuxer", __FUNCTION__);
119 delete m_pInputStream;
120 m_pInputStream = NULL;
124 CDemuxStream* pStream = NULL;
126 for (int i = 0; i < m_pDemuxer->GetNrOfStreams(); i++)
128 pStream = m_pDemuxer->GetStream(i);
129 if (pStream && pStream->type == STREAM_AUDIO)
136 if (m_nAudioStream == -1)
138 CLog::Log(LOGERROR, "%s: Could not find audio stream", __FUNCTION__);
141 delete m_pInputStream;
142 m_pInputStream = NULL;
146 CDVDStreamInfo hint(*pStream, true);
148 bool passthrough = AUDIO_IS_BITSTREAM(CSettings::Get().GetInt("audiooutput.mode"));
149 m_pAudioCodec = CDVDFactoryCodec::CreateAudioCodec(hint, passthrough);
152 CLog::Log(LOGERROR, "%s: Could not create audio codec", __FUNCTION__);
155 delete m_pInputStream;
156 m_pInputStream = NULL;
160 // we have to decode initial data in order to get channels/samplerate
161 // for sanity - we read no more than 10 packets
163 for (int nPacket=0; nPacket < 10 && (m_Channels == 0 || m_SampleRate == 0); nPacket++)
167 if (ReadPCM(dummy, nSize, &nSize) == READ_ERROR)
170 m_DataFormat = m_pAudioCodec->GetDataFormat();
171 m_BitsPerSample = CAEUtil::DataFormatToBits(m_DataFormat);
172 m_SampleRate = m_pAudioCodec->GetSampleRate();
173 m_EncodedSampleRate = m_pAudioCodec->GetEncodedSampleRate();
174 m_Channels = m_pAudioCodec->GetChannels();
175 m_ChannelInfo = m_pAudioCodec->GetChannelMap();
180 CLog::Log(LOGDEBUG, "%s: Could not decode data", __FUNCTION__);
186 if (m_Channels == 0) // no data - just guess and hope for the best
189 if (m_SampleRate == 0)
190 m_SampleRate = 44100;
192 m_TotalTime = m_pDemuxer->GetStreamLength();
193 m_Bitrate = m_pAudioCodec->GetBitRate();
194 m_pDemuxer->GetStreamCodecName(m_nAudioStream,m_CodecName);
196 m_strFileName = strFile;
202 void DVDPlayerCodec::DeInit()
205 CDVDDemuxUtils::FreeDemuxPacket(m_pPacket);
208 if (m_pDemuxer != NULL)
214 if (m_pInputStream != NULL)
216 delete m_pInputStream;
217 m_pInputStream = NULL;
220 if (m_pAudioCodec != NULL)
222 delete m_pAudioCodec;
223 m_pAudioCodec = NULL;
226 // cleanup format information
229 m_EncodedSampleRate = 0;
231 m_DataFormat = AE_FMT_INVALID;
243 int64_t DVDPlayerCodec::Seek(int64_t iSeekTime)
246 CDVDDemuxUtils::FreeDemuxPacket(m_pPacket);
249 m_pDemuxer->SeekTime((int)iSeekTime, false);
250 m_pAudioCodec->Reset();
258 int DVDPlayerCodec::ReadPCM(BYTE *pBuffer, int size, int *actualsize)
260 if (m_decoded && m_nDecodedLen > 0)
262 int nLen = (size<m_nDecodedLen)?size:m_nDecodedLen;
264 memcpy(pBuffer, m_decoded, *actualsize);
265 m_nDecodedLen -= nLen;
266 m_decoded += (*actualsize);
273 // dvdplayer returns a read error on a single invalid packet, while
274 // in paplayer READ_ERROR is a fatal error.
275 // Therefore skip over invalid packets here.
277 for (int tries = 0; decodeLen < 0 && tries < 2; ++tries)
279 if (m_pPacket && m_audioPos >= m_pPacket->iSize)
281 CDVDDemuxUtils::FreeDemuxPacket(m_pPacket);
286 if (m_pPacket == NULL)
290 m_pPacket = m_pDemuxer->Read();
291 } while (m_pPacket && m_pPacket->iStreamId != m_nAudioStream);
300 decodeLen = m_pAudioCodec->Decode(m_pPacket->pData + m_audioPos, m_pPacket->iSize - m_audioPos);
303 m_audioPos = m_pPacket->iSize; // skip packet
308 CDVDDemuxUtils::FreeDemuxPacket(m_pPacket);
314 m_audioPos += decodeLen;
316 m_nDecodedLen = m_pAudioCodec->GetData(&m_decoded);
318 *actualsize = (m_nDecodedLen <= size) ? m_nDecodedLen : size;
321 memcpy(pBuffer, m_decoded, *actualsize);
322 m_nDecodedLen -= *actualsize;
323 m_decoded += (*actualsize);
329 bool DVDPlayerCodec::CanInit()
334 bool DVDPlayerCodec::CanSeek()