1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #include "VideoPlayerCodec.h"
10 
11 #include "ServiceBroker.h"
12 #include "URL.h"
13 #include "cores/AudioEngine/AEResampleFactory.h"
14 #include "cores/AudioEngine/Interfaces/AE.h"
15 #include "cores/AudioEngine/Utils/AEUtil.h"
16 #include "cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h"
17 #include "cores/VideoPlayer/DVDDemuxers/DVDDemuxUtils.h"
18 #include "cores/VideoPlayer/DVDDemuxers/DVDFactoryDemuxer.h"
19 #include "cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.h"
20 #include "cores/VideoPlayer/DVDStreamInfo.h"
21 #include "music/tags/TagLoaderTagLib.h"
22 #include "utils/StringUtils.h"
23 #include "utils/log.h"
24 
VideoPlayerCodec()25 VideoPlayerCodec::VideoPlayerCodec()
26 {
27   m_CodecName = "VideoPlayer";
28   m_pDemuxer = NULL;
29   m_pInputStream = NULL;
30   m_pAudioCodec = NULL;
31   m_nAudioStream = -1;
32   m_nDecodedLen = 0;
33   m_bInited = false;
34   m_pResampler = NULL;
35   m_needConvert = false;
36   m_channels = 0;
37 
38   m_processInfo.reset(CProcessInfo::CreateInstance());
39 }
40 
~VideoPlayerCodec()41 VideoPlayerCodec::~VideoPlayerCodec()
42 {
43   DeInit();
44 }
45 
GetFormat()46 AEAudioFormat VideoPlayerCodec::GetFormat()
47 {
48   AEAudioFormat format;
49   if (m_pAudioCodec)
50   {
51     format = m_pAudioCodec->GetFormat();
52   }
53   return format;
54 }
55 
SetContentType(const std::string & strContent)56 void VideoPlayerCodec::SetContentType(const std::string &strContent)
57 {
58   m_strContentType = strContent;
59   StringUtils::ToLower(m_strContentType);
60 }
61 
SetPassthroughStreamType(CAEStreamInfo::DataType streamType)62 void  VideoPlayerCodec::SetPassthroughStreamType(CAEStreamInfo::DataType streamType)
63 {
64   m_srcFormat.m_streamInfo.m_type = streamType;
65 }
66 
Init(const CFileItem & file,unsigned int filecache)67 bool VideoPlayerCodec::Init(const CFileItem &file, unsigned int filecache)
68 {
69   // take precaution if Init()ialized earlier
70   if (m_bInited)
71   {
72     // keep things as is if Init() was done with known strFile
73     if (m_strFileName == file.GetDynPath())
74       return true;
75 
76     // got differing filename, so cleanup before starting over
77     DeInit();
78   }
79 
80   m_nDecodedLen = 0;
81 
82   CFileItem fileitem(file);
83   fileitem.SetMimeType(m_strContentType);
84   fileitem.SetMimeTypeForInternetFile();
85   m_pInputStream = CDVDFactoryInputStream::CreateInputStream(NULL, fileitem);
86   if (!m_pInputStream)
87   {
88     CLog::Log(LOGERROR, "{}: Error creating input stream for {}", __FUNCTION__, file.GetDynPath());
89     return false;
90   }
91 
92   //! @todo
93   //! convey CFileItem::ContentLookup() into Open()
94   if (!m_pInputStream->Open())
95   {
96     CLog::Log(LOGERROR, "{}: Error opening file {}", __FUNCTION__, file.GetDynPath());
97     if (m_pInputStream.use_count() > 1)
98       throw std::runtime_error("m_pInputStream reference count is greater than 1");
99     m_pInputStream.reset();
100     return false;
101   }
102 
103   m_pDemuxer = NULL;
104 
105   try
106   {
107     m_pDemuxer = CDVDFactoryDemuxer::CreateDemuxer(m_pInputStream);
108     if (!m_pDemuxer)
109     {
110       if (m_pInputStream.use_count() > 1)
111         throw std::runtime_error("m_pInputStream reference count is greater than 1");
112       m_pInputStream.reset();
113       CLog::Log(LOGERROR, "%s: Error creating demuxer", __FUNCTION__);
114       return false;
115     }
116   }
117   catch(...)
118   {
119     CLog::Log(LOGERROR, "%s: Exception thrown when opening demuxer", __FUNCTION__);
120     if (m_pDemuxer)
121     {
122       delete m_pDemuxer;
123       m_pDemuxer = NULL;
124     }
125     return false;
126   }
127 
128   CDemuxStream* pStream = NULL;
129   m_nAudioStream = -1;
130   int64_t demuxerId = -1;
131   for (auto stream : m_pDemuxer->GetStreams())
132   {
133     if (stream && stream->type == STREAM_AUDIO)
134     {
135       m_nAudioStream = stream->uniqueId;
136       demuxerId = stream->demuxerId;
137       pStream = stream;
138       break;
139     }
140   }
141 
142   if (m_nAudioStream == -1)
143   {
144     CLog::Log(LOGERROR, "%s: Could not find audio stream", __FUNCTION__);
145     delete m_pDemuxer;
146     m_pDemuxer = NULL;
147     if (m_pInputStream.use_count() > 1)
148       throw std::runtime_error("m_pInputStream reference count is greater than 1");
149     m_pInputStream.reset();
150     return false;
151   }
152 
153   CDVDStreamInfo hint(*pStream, true);
154 
155   CAEStreamInfo::DataType ptStreamTye =
156       GetPassthroughStreamType(hint.codec, hint.samplerate, hint.profile);
157   m_pAudioCodec = CDVDFactoryCodec::CreateAudioCodec(hint, *m_processInfo, true, true, ptStreamTye);
158   if (!m_pAudioCodec)
159   {
160     CLog::Log(LOGERROR, "%s: Could not create audio codec", __FUNCTION__);
161     delete m_pDemuxer;
162     m_pDemuxer = NULL;
163     if (m_pInputStream.use_count() > 1)
164       throw std::runtime_error("m_pInputStream reference count is greater than 1");
165     m_pInputStream.reset();
166     return false;
167   }
168 
169   //  Extract ReplayGain info
170   // tagLoaderTagLib.Load will try to determine tag type by file extension, so set fallback by contentType
171   std::string strFallbackFileExtension = "";
172   if (m_strContentType == "audio/aacp" ||
173       m_strContentType == "audio/aac")
174     strFallbackFileExtension = "m4a";
175   else if (m_strContentType == "audio/x-ms-wma")
176     strFallbackFileExtension = "wma";
177   else if (m_strContentType == "audio/x-ape" ||
178            m_strContentType == "audio/ape")
179     strFallbackFileExtension = "ape";
180   CTagLoaderTagLib tagLoaderTagLib;
181   tagLoaderTagLib.Load(file.GetDynPath(), m_tag, strFallbackFileExtension);
182 
183   // we have to decode initial data in order to get channels/samplerate
184   // for sanity - we read no more than 10 packets
185   int nErrors = 0;
186   for (int nPacket=0; nPacket < 10 && (m_channels == 0 || m_format.m_sampleRate == 0); nPacket++)
187   {
188     unsigned char dummy[256];
189     int nSize = 256;
190     if (ReadPCM(dummy, nSize, &nSize) == READ_ERROR)
191       ++nErrors;
192 
193     m_srcFormat = m_pAudioCodec->GetFormat();
194     m_format = m_srcFormat;
195     m_channels = m_srcFormat.m_channelLayout.Count();
196     m_bitsPerSample = CAEUtil::DataFormatToBits(m_srcFormat.m_dataFormat);
197     m_bitsPerCodedSample = static_cast<CDemuxStreamAudio*>(pStream)->iBitsPerSample;
198   }
199   if (nErrors >= 10)
200   {
201     CLog::Log(LOGDEBUG, "%s: Could not decode data", __FUNCTION__);
202     return false;
203   }
204 
205   // test if seeking is supported
206   m_bCanSeek = false;
207   if (m_pInputStream->Seek(0, SEEK_POSSIBLE))
208   {
209     if (Seek(1))
210     {
211       // rewind stream to beginning
212       Seek(0);
213       m_bCanSeek = true;
214     }
215     else
216     {
217       m_pInputStream->Seek(0, SEEK_SET);
218       if (!m_pDemuxer->Reset())
219         return false;
220     }
221   }
222 
223   if (m_channels == 0) // no data - just guess and hope for the best
224   {
225     m_srcFormat.m_channelLayout = CAEChannelInfo(AE_CH_LAYOUT_2_0);
226     m_channels = m_srcFormat.m_channelLayout.Count();
227   }
228 
229   if (m_srcFormat.m_sampleRate == 0)
230     m_srcFormat.m_sampleRate = 44100;
231 
232   m_TotalTime = m_pDemuxer->GetStreamLength();
233   m_bitRate = m_pAudioCodec->GetBitRate();
234   if (!m_bitRate && m_TotalTime)
235   {
236     m_bitRate = (int)(((m_pInputStream->GetLength()*1000) / m_TotalTime) * 8);
237   }
238   m_CodecName = m_pDemuxer->GetStreamCodecName(demuxerId, m_nAudioStream);
239 
240   m_needConvert = false;
241   if (NeedConvert(m_srcFormat.m_dataFormat))
242   {
243     m_needConvert = true;
244     m_pResampler = ActiveAE::CAEResampleFactory::Create();
245 
246     SampleConfig dstConfig, srcConfig;
247     dstConfig.channel_layout = CAEUtil::GetAVChannelLayout(m_srcFormat.m_channelLayout);
248     dstConfig.channels = m_channels;
249     dstConfig.sample_rate = m_srcFormat.m_sampleRate;
250     dstConfig.fmt = CAEUtil::GetAVSampleFormat(AE_FMT_FLOAT);
251     dstConfig.bits_per_sample = CAEUtil::DataFormatToUsedBits(AE_FMT_FLOAT);
252     dstConfig.dither_bits = CAEUtil::DataFormatToDitherBits(AE_FMT_FLOAT);
253 
254     srcConfig.channel_layout = CAEUtil::GetAVChannelLayout(m_srcFormat.m_channelLayout);
255     srcConfig.channels = m_channels;
256     srcConfig.sample_rate = m_srcFormat.m_sampleRate;
257     srcConfig.fmt = CAEUtil::GetAVSampleFormat(m_srcFormat.m_dataFormat);
258     srcConfig.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_srcFormat.m_dataFormat);
259     srcConfig.dither_bits = CAEUtil::DataFormatToDitherBits(m_srcFormat.m_dataFormat);
260 
261     m_pResampler->Init(dstConfig, srcConfig,
262                        false,
263                        false,
264                        M_SQRT1_2,
265                        NULL,
266                        AE_QUALITY_UNKNOWN,
267                        false);
268 
269     m_planes = AE_IS_PLANAR(m_srcFormat.m_dataFormat) ? m_channels : 1;
270     m_format = m_srcFormat;
271     m_format.m_dataFormat = AE_FMT_FLOAT;
272     m_bitsPerSample = CAEUtil::DataFormatToBits(m_format.m_dataFormat);
273   }
274 
275   m_strFileName = file.GetDynPath();
276   m_bInited = true;
277 
278   return true;
279 }
280 
DeInit()281 void VideoPlayerCodec::DeInit()
282 {
283   if (m_pDemuxer != NULL)
284   {
285     delete m_pDemuxer;
286     m_pDemuxer = NULL;
287   }
288 
289   if (m_pInputStream.use_count() > 1)
290     throw std::runtime_error("m_pInputStream reference count is greater than 1");
291   m_pInputStream.reset();
292 
293   if (m_pAudioCodec != NULL)
294   {
295     delete m_pAudioCodec;
296     m_pAudioCodec = NULL;
297   }
298 
299   delete m_pResampler;
300   m_pResampler = NULL;
301 
302   // cleanup format information
303   m_TotalTime = 0;
304   m_bitsPerSample = 0;
305   m_bitRate = 0;
306   m_channels = 0;
307   m_format.m_dataFormat = AE_FMT_INVALID;
308 
309   m_nDecodedLen = 0;
310 
311   m_strFileName = "";
312   m_bInited = false;
313 }
314 
Seek(int64_t iSeekTime)315 bool VideoPlayerCodec::Seek(int64_t iSeekTime)
316 {
317   // default to announce backwards seek if !m_pPacket to not make FFmpeg
318   // skip mpeg audio frames at playback start
319   bool seekback = true;
320 
321   bool ret = m_pDemuxer->SeekTime((int)iSeekTime, seekback);
322   m_pAudioCodec->Reset();
323 
324   m_nDecodedLen = 0;
325 
326   return ret;
327 }
328 
ReadPCM(unsigned char * pBuffer,int size,int * actualsize)329 int VideoPlayerCodec::ReadPCM(unsigned char *pBuffer, int size, int *actualsize)
330 {
331   if (m_nDecodedLen > 0)
332   {
333     int nLen = (size<m_nDecodedLen)?size:m_nDecodedLen;
334     *actualsize = nLen;
335     if (m_needConvert)
336     {
337       int samples = *actualsize / (m_bitsPerSample>>3);
338       int frames = samples / m_channels;
339       m_pResampler->Resample(&pBuffer, frames, m_audioFrame.data, frames, 1.0);
340       for (int i=0; i<m_planes; i++)
341       {
342         m_audioFrame.data[i] += frames*m_srcFormat.m_frameSize/m_planes;
343       }
344     }
345     else
346     {
347       memcpy(pBuffer, m_audioFrame.data[0], *actualsize);
348       m_audioFrame.data[0] += (*actualsize);
349     }
350     m_nDecodedLen -= nLen;
351     return READ_SUCCESS;
352   }
353 
354   m_nDecodedLen = 0;
355   m_pAudioCodec->GetData(m_audioFrame);
356   int bytes = m_audioFrame.nb_frames * m_audioFrame.framesize;
357 
358   if (!bytes)
359   {
360     DemuxPacket* pPacket;
361     do
362     {
363       pPacket = m_pDemuxer->Read();
364     } while (pPacket && pPacket->iStreamId != m_nAudioStream);
365 
366     if (!pPacket)
367     {
368       return READ_EOF;
369     }
370 
371     pPacket->pts = DVD_NOPTS_VALUE;
372     pPacket->dts = DVD_NOPTS_VALUE;
373 
374     int ret = m_pAudioCodec->AddData(*pPacket);
375     CDVDDemuxUtils::FreeDemuxPacket(pPacket);
376     if (ret < 0)
377     {
378       return READ_ERROR;
379     }
380 
381     m_pAudioCodec->GetData(m_audioFrame);
382     bytes = m_audioFrame.nb_frames * m_audioFrame.framesize;
383   }
384 
385   m_nDecodedLen = bytes;
386   // scale decoded bytes to destination format
387   if (m_needConvert)
388     m_nDecodedLen *= (m_bitsPerSample>>3) / (m_srcFormat.m_frameSize / m_channels);
389 
390   *actualsize = (m_nDecodedLen <= size) ? m_nDecodedLen : size;
391   if (*actualsize > 0)
392   {
393     if (m_needConvert)
394     {
395       int samples = *actualsize / (m_bitsPerSample>>3);
396       int frames = samples / m_channels;
397       m_pResampler->Resample(&pBuffer, frames, m_audioFrame.data, frames, 1.0);
398       for (int i=0; i<m_planes; i++)
399       {
400         m_audioFrame.data[i] += frames*m_srcFormat.m_frameSize/m_planes;
401       }
402     }
403     else
404     {
405       memcpy(pBuffer, m_audioFrame.data[0], *actualsize);
406       m_audioFrame.data[0] += *actualsize;
407     }
408     m_nDecodedLen -= *actualsize;
409   }
410 
411   return READ_SUCCESS;
412 }
413 
ReadRaw(uint8_t ** pBuffer,int * bufferSize)414 int VideoPlayerCodec::ReadRaw(uint8_t **pBuffer, int *bufferSize)
415 {
416   DemuxPacket* pPacket;
417 
418   m_nDecodedLen = 0;
419   DVDAudioFrame audioframe;
420 
421   m_pAudioCodec->GetData(audioframe);
422   if (audioframe.nb_frames)
423   {
424     return READ_SUCCESS;
425   }
426 
427   do
428   {
429     pPacket = m_pDemuxer->Read();
430   } while (pPacket && pPacket->iStreamId != m_nAudioStream);
431 
432   if (!pPacket)
433   {
434     return READ_EOF;
435   }
436   pPacket->pts = DVD_NOPTS_VALUE;
437   pPacket->dts = DVD_NOPTS_VALUE;
438   int ret = m_pAudioCodec->AddData(*pPacket);
439   CDVDDemuxUtils::FreeDemuxPacket(pPacket);
440   if (ret < 0)
441   {
442     return READ_ERROR;
443   }
444 
445   m_pAudioCodec->GetData(audioframe);
446   if (audioframe.nb_frames)
447   {
448     *bufferSize = audioframe.nb_frames;
449     *pBuffer = audioframe.data[0];
450   }
451   else
452   {
453     *bufferSize = 0;
454   }
455 
456   return READ_SUCCESS;
457 }
458 
CanInit()459 bool VideoPlayerCodec::CanInit()
460 {
461   return true;
462 }
463 
CanSeek()464 bool VideoPlayerCodec::CanSeek()
465 {
466   return m_bCanSeek;
467 }
468 
NeedConvert(AEDataFormat fmt)469 bool VideoPlayerCodec::NeedConvert(AEDataFormat fmt)
470 {
471   if (fmt == AE_FMT_RAW)
472     return false;
473 
474   switch(fmt)
475   {
476     case AE_FMT_U8:
477     case AE_FMT_S16NE:
478     case AE_FMT_S32NE:
479     case AE_FMT_FLOAT:
480     case AE_FMT_DOUBLE:
481       return false;
482     default:
483       return true;
484   }
485 }
486 
GetPassthroughStreamType(AVCodecID codecId,int samplerate,int profile)487 CAEStreamInfo::DataType VideoPlayerCodec::GetPassthroughStreamType(AVCodecID codecId,
488                                                                    int samplerate,
489                                                                    int profile)
490 {
491   AEAudioFormat format;
492   format.m_dataFormat = AE_FMT_RAW;
493   format.m_sampleRate = samplerate;
494   format.m_streamInfo.m_type = CAEStreamInfo::DataType::STREAM_TYPE_NULL;
495   switch (codecId)
496   {
497     case AV_CODEC_ID_AC3:
498       format.m_streamInfo.m_type = CAEStreamInfo::STREAM_TYPE_AC3;
499       format.m_streamInfo.m_sampleRate = samplerate;
500       break;
501 
502     case AV_CODEC_ID_EAC3:
503       format.m_streamInfo.m_type = CAEStreamInfo::STREAM_TYPE_EAC3;
504       format.m_streamInfo.m_sampleRate = samplerate;
505       break;
506 
507     case AV_CODEC_ID_DTS:
508       if (profile == FF_PROFILE_DTS_HD_HRA)
509         format.m_streamInfo.m_type = CAEStreamInfo::STREAM_TYPE_DTSHD;
510       else
511         format.m_streamInfo.m_type = CAEStreamInfo::STREAM_TYPE_DTSHD_MA;
512       format.m_streamInfo.m_sampleRate = samplerate;
513       break;
514 
515     case AV_CODEC_ID_TRUEHD:
516       format.m_streamInfo.m_type = CAEStreamInfo::STREAM_TYPE_TRUEHD;
517       format.m_streamInfo.m_sampleRate = samplerate;
518       break;
519 
520     default:
521       format.m_streamInfo.m_type = CAEStreamInfo::STREAM_TYPE_NULL;
522   }
523 
524   bool supports = CServiceBroker::GetActiveAE()->SupportsRaw(format);
525 
526   if (!supports && codecId == AV_CODEC_ID_DTS)
527   {
528     format.m_streamInfo.m_type = CAEStreamInfo::STREAM_TYPE_DTSHD_CORE;
529     supports = CServiceBroker::GetActiveAE()->SupportsRaw(format);
530   }
531 
532   if (supports)
533     return format.m_streamInfo.m_type;
534   else
535     return CAEStreamInfo::DataType::STREAM_TYPE_NULL;
536 }
537