c60abc860c17c9f2e042e5e1ccf2d57dd06e77c1
[vuplus_xbmc] / xbmc / cores / paplayer / DVDPlayerCodec.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 "DVDPlayerCodec.h"
22 #include "cores/AudioEngine/Utils/AEUtil.h"
23
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"
32 #include "URL.h"
33
34 #include "AudioDecoder.h"
35
36 DVDPlayerCodec::DVDPlayerCodec()
37 {
38   m_CodecName = "DVDPlayer";
39   m_pDemuxer = NULL;
40   m_pInputStream = NULL;
41   m_pAudioCodec = NULL;
42   m_nAudioStream = -1;
43   m_audioPos = 0;
44   m_pPacket = NULL;
45   m_decoded = NULL;
46   m_nDecodedLen = 0;
47   m_strFileName = "";
48   m_bInited = false;
49 }
50
51 DVDPlayerCodec::~DVDPlayerCodec()
52 {
53   DeInit();
54 }
55
56 void DVDPlayerCodec::SetContentType(const CStdString &strContent)
57 {
58   m_strContentType = strContent;
59 }
60
61 bool DVDPlayerCodec::Init(const CStdString &strFile, unsigned int filecache)
62 {
63   // take precaution if Init()ialized earlier
64   if (m_bInited)
65   {
66     // keep things as is if Init() was done with known strFile
67     if (m_strFileName == strFile)
68       return true;
69
70     // got differing filename, so cleanup before starting over
71     DeInit();
72   }
73
74   m_decoded = NULL;
75   m_nDecodedLen = 0;
76
77   CStdString strFileToOpen = strFile;
78
79   CURL urlFile(strFile);
80   if (urlFile.GetProtocol() == "shout" )
81     strFileToOpen.replace(0, 8, "http://");
82
83   m_pInputStream = CDVDFactoryInputStream::CreateInputStream(NULL, strFileToOpen, m_strContentType);
84   if (!m_pInputStream)
85   {
86     CLog::Log(LOGERROR, "%s: Error creating input stream for %s", __FUNCTION__, strFileToOpen.c_str());
87     return false;
88   }
89
90   if (!m_pInputStream->Open(strFileToOpen.c_str(), m_strContentType))
91   {
92     CLog::Log(LOGERROR, "%s: Error opening file %s", __FUNCTION__, strFileToOpen.c_str());
93     if (m_pInputStream)
94       delete m_pInputStream;
95     m_pInputStream = NULL;
96     return false;
97   }
98
99   m_pDemuxer = NULL;
100
101   try
102   {
103     m_pDemuxer = CDVDFactoryDemuxer::CreateDemuxer(m_pInputStream);
104     if (!m_pDemuxer)
105     {
106       delete m_pInputStream;
107       m_pInputStream = NULL;
108       CLog::Log(LOGERROR, "%s: Error creating demuxer", __FUNCTION__);
109       return false;
110     }
111   }
112   catch(...)
113   {
114     CLog::Log(LOGERROR, "%s: Exception thrown when opening demuxer", __FUNCTION__);
115     if (m_pDemuxer)
116     {
117       delete m_pDemuxer;
118       m_pDemuxer = NULL;
119     }
120     delete m_pInputStream;
121     m_pInputStream = NULL;
122     return false;
123   }
124
125   CDemuxStream* pStream = NULL;
126   m_nAudioStream = -1;
127   for (int i = 0; i < m_pDemuxer->GetNrOfStreams(); i++)
128   {
129     pStream = m_pDemuxer->GetStream(i);
130     if (pStream && pStream->type == STREAM_AUDIO)
131     {
132       m_nAudioStream = i;
133       break;
134     }
135   }
136
137   if (m_nAudioStream == -1)
138   {
139     CLog::Log(LOGERROR, "%s: Could not find audio stream", __FUNCTION__);
140     delete m_pDemuxer;
141     m_pDemuxer = NULL;
142     delete m_pInputStream;
143     m_pInputStream = NULL;
144     return false;
145   }
146
147   CDVDStreamInfo hint(*pStream, true);
148
149   m_pAudioCodec = CDVDFactoryCodec::CreateAudioCodec(hint);
150   if (!m_pAudioCodec)
151   {
152     CLog::Log(LOGERROR, "%s: Could not create audio codec", __FUNCTION__);
153     delete m_pDemuxer;
154     m_pDemuxer = NULL;
155     delete m_pInputStream;
156     m_pInputStream = NULL;
157     return false;
158   }
159
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);
171
172   // we have to decode initial data in order to get channels/samplerate
173   // for sanity - we read no more than 10 packets
174   int nErrors = 0;
175   for (int nPacket=0; nPacket < 10 && (m_Channels == 0 || m_SampleRate == 0); nPacket++)
176   {
177     BYTE dummy[256];
178     int nSize = 256;
179     if (ReadPCM(dummy, nSize, &nSize) == READ_ERROR)
180       ++nErrors;
181
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;
189   }
190   if (nErrors >= 10)
191   {
192     CLog::Log(LOGDEBUG, "%s: Could not decode data", __FUNCTION__);
193     return false;
194   }
195
196   // test if seeking is supported
197   if (Seek(1) != DVD_NOPTS_VALUE)
198   {
199     // rewind stream to beginning
200     Seek(0);
201     m_bCanSeek = true;
202   }
203   else
204   {
205     m_pInputStream->Seek(0, SEEK_SET);
206     m_pDemuxer->Reset();
207     m_bCanSeek = false;
208   }
209
210   if (m_Channels == 0) // no data - just guess and hope for the best
211     m_Channels = 2;
212
213   if (m_SampleRate == 0)
214     m_SampleRate = 44100;
215
216   m_TotalTime = m_pDemuxer->GetStreamLength();
217   m_Bitrate = m_pAudioCodec->GetBitRate();
218   if (!m_Bitrate && m_TotalTime)
219   {
220     m_Bitrate = (int)(((m_pInputStream->GetLength()*1000) / m_TotalTime) * 8);
221   }
222   m_pDemuxer->GetStreamCodecName(m_nAudioStream,m_CodecName);
223
224   m_strFileName = strFile;
225   m_bInited = true;
226
227   return true;
228 }
229
230 void DVDPlayerCodec::DeInit()
231 {
232   if (m_pPacket)
233     CDVDDemuxUtils::FreeDemuxPacket(m_pPacket);
234   m_pPacket = NULL;
235
236   if (m_pDemuxer != NULL)
237   {
238     delete m_pDemuxer;
239     m_pDemuxer = NULL;
240   }
241
242   if (m_pInputStream != NULL)
243   {
244     delete m_pInputStream;
245     m_pInputStream = NULL;
246   }
247
248   if (m_pAudioCodec != NULL)
249   {
250     delete m_pAudioCodec;
251     m_pAudioCodec = NULL;
252   }
253
254   // cleanup format information
255   m_TotalTime = 0;
256   m_SampleRate = 0;
257   m_EncodedSampleRate = 0;
258   m_BitsPerSample = 0;
259   m_DataFormat = AE_FMT_INVALID;
260   m_Channels = 0;
261   m_Bitrate = 0;
262
263   m_audioPos = 0;
264   m_decoded = NULL;
265   m_nDecodedLen = 0;
266
267   m_strFileName = "";
268   m_bInited = false;
269 }
270
271 int64_t DVDPlayerCodec::Seek(int64_t iSeekTime)
272 {
273   if (m_pPacket)
274     CDVDDemuxUtils::FreeDemuxPacket(m_pPacket);
275   m_pPacket = NULL;
276
277   bool ret = m_pDemuxer->SeekTime((int)iSeekTime, false);
278   m_pAudioCodec->Reset();
279
280   m_decoded = NULL;
281   m_nDecodedLen = 0;
282
283   if (!ret)
284     return DVD_NOPTS_VALUE;
285
286   return iSeekTime;
287 }
288
289 int DVDPlayerCodec::ReadPCM(BYTE *pBuffer, int size, int *actualsize)
290 {
291   if (m_decoded && m_nDecodedLen > 0)
292   {
293     int nLen = (size<m_nDecodedLen)?size:m_nDecodedLen;
294     *actualsize = nLen;
295     memcpy(pBuffer, m_decoded, *actualsize);
296     m_nDecodedLen -= nLen;
297     m_decoded += (*actualsize);
298     return READ_SUCCESS;
299   }
300
301   m_decoded = NULL;
302   m_nDecodedLen = 0;
303
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.
307   int decodeLen = -1;
308   for (int tries = 0; decodeLen < 0 && tries < 2; ++tries)
309   {
310     if (m_pPacket && m_audioPos >= m_pPacket->iSize)
311     {
312       CDVDDemuxUtils::FreeDemuxPacket(m_pPacket);
313       m_audioPos = 0;
314       m_pPacket = NULL;
315     }
316
317     if (m_pPacket == NULL)
318     {
319       do
320       {
321         m_pPacket = m_pDemuxer->Read();
322       } while (m_pPacket && m_pPacket->iStreamId != m_nAudioStream);
323
324       if (!m_pPacket)
325       {
326         return READ_EOF;
327       }
328       m_audioPos = 0;
329     }
330
331     decodeLen = m_pAudioCodec->Decode(m_pPacket->pData + m_audioPos, m_pPacket->iSize - m_audioPos);
332
333     if (decodeLen < 0)
334       m_audioPos = m_pPacket->iSize; // skip packet
335   }
336
337   if (decodeLen < 0)
338   {
339     CDVDDemuxUtils::FreeDemuxPacket(m_pPacket);
340     m_pPacket = NULL;
341     m_audioPos = 0;
342     return READ_ERROR;
343   }
344
345   m_audioPos += decodeLen;
346
347   m_nDecodedLen = m_pAudioCodec->GetData(&m_decoded);
348
349   *actualsize = (m_nDecodedLen <= size) ? m_nDecodedLen : size;
350   if (*actualsize > 0)
351   {
352     memcpy(pBuffer, m_decoded, *actualsize);
353     m_nDecodedLen -= *actualsize;
354     m_decoded += (*actualsize);
355   }
356
357   return READ_SUCCESS;
358 }
359
360 bool DVDPlayerCodec::CanInit()
361 {
362   return true;
363 }
364
365 bool DVDPlayerCodec::CanSeek()
366 {
367   return m_bCanSeek;
368 }