PageRenderTime 55ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp

https://github.com/weitao2012/android-1
C++ | 1316 lines | 1003 code | 174 blank | 139 comment | 350 complexity | 330f3c07fcf91351ef66c5d91ebf6532 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. /*
  2. * Copyright (C) 2005-2008 Team XBMC
  3. * http://www.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, write to
  17. * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  18. * http://www.gnu.org/copyleft/gpl.html
  19. *
  20. */
  21. #include "system.h"
  22. #ifndef __STDC_CONSTANT_MACROS
  23. #define __STDC_CONSTANT_MACROS
  24. #endif
  25. #ifndef __STDC_LIMIT_MACROS
  26. #define __STDC_LIMIT_MACROS
  27. #endif
  28. #ifdef _LINUX
  29. #include "stdint.h"
  30. #endif
  31. #include "DVDDemuxFFmpeg.h"
  32. #include "DVDInputStreams/DVDInputStream.h"
  33. #include "DVDInputStreams/DVDInputStreamNavigator.h"
  34. #ifdef HAVE_LIBBLURAY
  35. #include "DVDInputStreams/DVDInputStreamBluray.h"
  36. #endif
  37. #include "DVDDemuxUtils.h"
  38. #include "DVDClock.h" // for DVD_TIME_BASE
  39. #include "commons/Exception.h"
  40. #include "settings/AdvancedSettings.h"
  41. #include "settings/GUISettings.h"
  42. #include "filesystem/File.h"
  43. #include "filesystem/Directory.h"
  44. #include "utils/log.h"
  45. #include "threads/Thread.h"
  46. #include "threads/SystemClock.h"
  47. #include "utils/TimeUtils.h"
  48. void CDemuxStreamAudioFFmpeg::GetStreamInfo(std::string& strInfo)
  49. {
  50. if(!m_stream) return;
  51. char temp[128];
  52. m_parent->m_dllAvCodec.avcodec_string(temp, 128, m_stream->codec, 0);
  53. strInfo = temp;
  54. }
  55. void CDemuxStreamAudioFFmpeg::GetStreamName(std::string& strInfo)
  56. {
  57. if(!m_stream) return;
  58. if(!m_description.empty())
  59. strInfo = m_description;
  60. else
  61. CDemuxStream::GetStreamName(strInfo);
  62. }
  63. void CDemuxStreamSubtitleFFmpeg::GetStreamName(std::string& strInfo)
  64. {
  65. if(!m_stream) return;
  66. if(!m_description.empty())
  67. strInfo = m_description;
  68. else
  69. CDemuxStream::GetStreamName(strInfo);
  70. }
  71. void CDemuxStreamVideoFFmpeg::GetStreamInfo(std::string& strInfo)
  72. {
  73. if(!m_stream) return;
  74. char temp[128];
  75. m_parent->m_dllAvCodec.avcodec_string(temp, 128, m_stream->codec, 0);
  76. strInfo = temp;
  77. }
  78. void CDemuxStreamSubtitleFFmpeg::GetStreamInfo(std::string& strInfo)
  79. {
  80. if(!m_stream) return;
  81. char temp[128];
  82. m_parent->m_dllAvCodec.avcodec_string(temp, 128, m_stream->codec, 0);
  83. strInfo = temp;
  84. }
  85. // these need to be put somewhere that are compiled, we should have some better place for it
  86. CCriticalSection DllAvCodec::m_critSection;
  87. static CCriticalSection m_logSection;
  88. std::map<uintptr_t, CStdString> g_logbuffer;
  89. void ff_avutil_log(void* ptr, int level, const char* format, va_list va)
  90. {
  91. CSingleLock lock(m_logSection);
  92. uintptr_t threadId = (uintptr_t)CThread::GetCurrentThreadId();
  93. CStdString &buffer = g_logbuffer[threadId];
  94. AVClass* avc= ptr ? *(AVClass**)ptr : NULL;
  95. if(level >= AV_LOG_DEBUG && g_advancedSettings.m_logLevel <= LOG_LEVEL_DEBUG_SAMBA)
  96. return;
  97. else if(g_advancedSettings.m_logLevel <= LOG_LEVEL_NORMAL)
  98. return;
  99. int type;
  100. switch(level)
  101. {
  102. case AV_LOG_INFO : type = LOGINFO; break;
  103. case AV_LOG_ERROR : type = LOGERROR; break;
  104. case AV_LOG_DEBUG :
  105. default : type = LOGDEBUG; break;
  106. }
  107. CStdString message, prefix;
  108. message.FormatV(format, va);
  109. prefix.Format("ffmpeg[%X]: ", threadId);
  110. if(avc)
  111. {
  112. if(avc->item_name)
  113. prefix += CStdString("[") + avc->item_name(ptr) + "] ";
  114. else if(avc->class_name)
  115. prefix += CStdString("[") + avc->class_name + "] ";
  116. }
  117. buffer += message;
  118. int pos, start = 0;
  119. while( (pos = buffer.find_first_of('\n', start)) >= 0 )
  120. {
  121. if(pos>start)
  122. CLog::Log(type, "%s%s", prefix.c_str(), buffer.substr(start, pos-start).c_str());
  123. start = pos+1;
  124. }
  125. buffer.erase(0, start);
  126. }
  127. static void ff_flush_avutil_log_buffers(void)
  128. {
  129. CSingleLock lock(DllAvCodec::m_critSection);
  130. /* Loop through the logbuffer list and remove any blank buffers
  131. If the thread using the buffer is still active, it will just
  132. add a new buffer next time it writes to the log */
  133. std::map<uintptr_t, CStdString>::iterator it;
  134. for (it = g_logbuffer.begin(); it != g_logbuffer.end(); )
  135. if ((*it).second.IsEmpty())
  136. g_logbuffer.erase(it++);
  137. else
  138. ++it;
  139. }
  140. static XbmcThreads::ThreadLocal<CDVDDemuxFFmpeg> g_demuxer;
  141. static int interrupt_cb(void* unused)
  142. {
  143. CDVDDemuxFFmpeg* demuxer = g_demuxer.get();
  144. if(demuxer && demuxer->Aborted())
  145. return 1;
  146. return 0;
  147. }
  148. ////////////////////////////////////////////////////////////////////////////////////////////////
  149. ////////////////////////////////////////////////////////////////////////////////////////////////
  150. /*
  151. static int dvd_file_open(URLContext *h, const char *filename, int flags)
  152. {
  153. return -1;
  154. }
  155. */
  156. static int dvd_file_read(void *h, uint8_t* buf, int size)
  157. {
  158. if(interrupt_cb(NULL))
  159. return -1;
  160. CDVDInputStream* pInputStream = (CDVDInputStream*)h;
  161. return pInputStream->Read(buf, size);
  162. }
  163. /*
  164. static int dvd_file_write(URLContext *h, BYTE* buf, int size)
  165. {
  166. return -1;
  167. }
  168. */
  169. static offset_t dvd_file_seek(void *h, offset_t pos, int whence)
  170. {
  171. if(interrupt_cb(NULL))
  172. return -1;
  173. CDVDInputStream* pInputStream = (CDVDInputStream*)h;
  174. if(whence == AVSEEK_SIZE)
  175. return pInputStream->GetLength();
  176. else
  177. return pInputStream->Seek(pos, whence & ~AVSEEK_FORCE);
  178. }
  179. ////////////////////////////////////////////////////////////////////////////////////////////////
  180. ////////////////////////////////////////////////////////////////////////////////////////////////
  181. CDVDDemuxFFmpeg::CDVDDemuxFFmpeg() : CDVDDemux()
  182. {
  183. m_pFormatContext = NULL;
  184. m_pInput = NULL;
  185. m_ioContext = NULL;
  186. for (int i = 0; i < MAX_STREAMS; i++) m_streams[i] = NULL;
  187. m_iCurrentPts = DVD_NOPTS_VALUE;
  188. }
  189. CDVDDemuxFFmpeg::~CDVDDemuxFFmpeg()
  190. {
  191. Dispose();
  192. ff_flush_avutil_log_buffers();
  193. }
  194. bool CDVDDemuxFFmpeg::Aborted()
  195. {
  196. if(m_timeout.IsTimePast())
  197. return true;
  198. return false;
  199. }
  200. bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput)
  201. {
  202. AVInputFormat* iformat = NULL;
  203. std::string strFile;
  204. m_iCurrentPts = DVD_NOPTS_VALUE;
  205. m_speed = DVD_PLAYSPEED_NORMAL;
  206. g_demuxer.set(this);
  207. m_program = UINT_MAX;
  208. const AVIOInterruptCB int_cb = { interrupt_cb, NULL };
  209. if (!pInput) return false;
  210. if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load()) {
  211. CLog::Log(LOGERROR,"CDVDDemuxFFmpeg::Open - failed to load ffmpeg libraries");
  212. return false;
  213. }
  214. // register codecs
  215. m_dllAvFormat.av_register_all();
  216. m_pInput = pInput;
  217. strFile = m_pInput->GetFileName();
  218. bool streaminfo = true; /* set to true if we want to look for streams before playback*/
  219. if( m_pInput->GetContent().length() > 0 )
  220. {
  221. std::string content = m_pInput->GetContent();
  222. /* check if we can get a hint from content */
  223. if ( content.compare("video/x-vobsub") == 0 )
  224. iformat = m_dllAvFormat.av_find_input_format("mpeg");
  225. else if( content.compare("video/x-dvd-mpeg") == 0 )
  226. iformat = m_dllAvFormat.av_find_input_format("mpeg");
  227. else if( content.compare("video/x-mpegts") == 0 )
  228. iformat = m_dllAvFormat.av_find_input_format("mpegts");
  229. else if( content.compare("multipart/x-mixed-replace") == 0 )
  230. iformat = m_dllAvFormat.av_find_input_format("mjpeg");
  231. }
  232. // try to abort after 30 seconds
  233. m_timeout.Set(30000);
  234. if( m_pInput->IsStreamType(DVDSTREAM_TYPE_FFMPEG) )
  235. {
  236. // special stream type that makes avformat handle file opening
  237. // allows internal ffmpeg protocols to be used
  238. int result=-1;
  239. if (strFile.substr(0,6) == "mms://")
  240. {
  241. // try mmsh, then mmst
  242. CStdString strFile2;
  243. strFile2.Format("mmsh://%s",strFile.substr(6,strFile.size()-6).c_str());
  244. result = m_dllAvFormat.avformat_open_input(&m_pFormatContext, strFile2.c_str(), iformat, NULL);
  245. if (result < 0)
  246. {
  247. strFile = "mmst://";
  248. strFile += strFile2.Mid(7).c_str();
  249. }
  250. }
  251. if (result < 0 && m_dllAvFormat.avformat_open_input(&m_pFormatContext, strFile.c_str(), iformat, NULL) < 0 )
  252. {
  253. CLog::Log(LOGDEBUG, "Error, could not open file %s", strFile.c_str());
  254. Dispose();
  255. return false;
  256. }
  257. }
  258. else
  259. {
  260. unsigned char* buffer = (unsigned char*)m_dllAvUtil.av_malloc(FFMPEG_FILE_BUFFER_SIZE);
  261. m_ioContext = m_dllAvFormat.avio_alloc_context(buffer, FFMPEG_FILE_BUFFER_SIZE, 0, m_pInput, dvd_file_read, NULL, dvd_file_seek);
  262. m_ioContext->max_packet_size = m_pInput->GetBlockSize();
  263. if(m_ioContext->max_packet_size)
  264. m_ioContext->max_packet_size *= FFMPEG_FILE_BUFFER_SIZE / m_ioContext->max_packet_size;
  265. if(m_pInput->Seek(0, SEEK_POSSIBLE) == 0)
  266. m_ioContext->seekable = 0;
  267. if( iformat == NULL )
  268. {
  269. // let ffmpeg decide which demuxer we have to open
  270. bool trySPDIFonly = (m_pInput->GetContent() == "audio/x-spdif-compressed");
  271. if (!trySPDIFonly)
  272. m_dllAvFormat.av_probe_input_buffer(m_ioContext, &iformat, strFile.c_str(), NULL, 0, 0);
  273. // Use the more low-level code in case we have been built against an old
  274. // FFmpeg without the above av_probe_input_buffer(), or in case we only
  275. // want to probe for spdif (DTS or IEC 61937) compressed audio
  276. // specifically, or in case the file is a wav which may contain DTS or
  277. // IEC 61937 (e.g. ac3-in-wav) and we want to check for those formats.
  278. if (trySPDIFonly || (iformat && strcmp(iformat->name, "wav") == 0))
  279. {
  280. AVProbeData pd;
  281. BYTE probe_buffer[FFMPEG_FILE_BUFFER_SIZE + AVPROBE_PADDING_SIZE];
  282. // init probe data
  283. pd.buf = probe_buffer;
  284. pd.filename = strFile.c_str();
  285. // read data using avformat's buffers
  286. pd.buf_size = m_dllAvFormat.avio_read(m_ioContext, pd.buf, m_ioContext->max_packet_size ? m_ioContext->max_packet_size : m_ioContext->buffer_size);
  287. if (pd.buf_size <= 0)
  288. {
  289. CLog::Log(LOGERROR, "%s - error reading from input stream, %s", __FUNCTION__, strFile.c_str());
  290. return false;
  291. }
  292. memset(pd.buf+pd.buf_size, 0, AVPROBE_PADDING_SIZE);
  293. // restore position again
  294. m_dllAvFormat.avio_seek(m_ioContext , 0, SEEK_SET);
  295. // the advancedsetting is for allowing the user to force outputting the
  296. // 44.1 kHz DTS wav file as PCM, so that an A/V receiver can decode
  297. // it (this is temporary until we handle 44.1 kHz passthrough properly)
  298. if (trySPDIFonly || (iformat && strcmp(iformat->name, "wav") == 0 && !g_advancedSettings.m_dvdplayerIgnoreDTSinWAV))
  299. {
  300. // check for spdif and dts
  301. // This is used with wav files and audio CDs that may contain
  302. // a DTS or AC3 track padded for S/PDIF playback. If neither of those
  303. // is present, we assume it is PCM audio.
  304. // AC3 is always wrapped in iec61937 (ffmpeg "spdif"), while DTS
  305. // may be just padded.
  306. AVInputFormat *iformat2;
  307. iformat2 = m_dllAvFormat.av_find_input_format("spdif");
  308. if (iformat2 && iformat2->read_probe(&pd) > AVPROBE_SCORE_MAX / 4)
  309. {
  310. iformat = iformat2;
  311. }
  312. else
  313. {
  314. // not spdif or no spdif demuxer, try dts
  315. iformat2 = m_dllAvFormat.av_find_input_format("dts");
  316. if (iformat2 && iformat2->read_probe(&pd) > AVPROBE_SCORE_MAX / 4)
  317. {
  318. iformat = iformat2;
  319. }
  320. else if (trySPDIFonly)
  321. {
  322. // not dts either, return false in case we were explicitely
  323. // requested to only check for S/PDIF padded compressed audio
  324. CLog::Log(LOGDEBUG, "%s - not spdif or dts file, fallbacking", __FUNCTION__);
  325. return false;
  326. }
  327. }
  328. }
  329. }
  330. if(!iformat)
  331. {
  332. std::string content = m_pInput->GetContent();
  333. /* check if we can get a hint from content */
  334. if( content.compare("audio/aacp") == 0 )
  335. iformat = m_dllAvFormat.av_find_input_format("aac");
  336. else if( content.compare("audio/aac") == 0 )
  337. iformat = m_dllAvFormat.av_find_input_format("aac");
  338. else if( content.compare("video/flv") == 0 )
  339. iformat = m_dllAvFormat.av_find_input_format("flv");
  340. else if( content.compare("video/x-flv") == 0 )
  341. iformat = m_dllAvFormat.av_find_input_format("flv");
  342. }
  343. if (!iformat)
  344. {
  345. CLog::Log(LOGERROR, "%s - error probing input format, %s", __FUNCTION__, strFile.c_str());
  346. return false;
  347. }
  348. else
  349. {
  350. if (iformat->name)
  351. CLog::Log(LOGDEBUG, "%s - probing detected format [%s]", __FUNCTION__, iformat->name);
  352. else
  353. CLog::Log(LOGDEBUG, "%s - probing detected unnamed format", __FUNCTION__);
  354. }
  355. }
  356. // open the demuxer
  357. m_pFormatContext = m_dllAvFormat.avformat_alloc_context();
  358. m_pFormatContext->pb = m_ioContext;
  359. if (m_dllAvFormat.avformat_open_input(&m_pFormatContext, strFile.c_str(), iformat, NULL) < 0)
  360. {
  361. CLog::Log(LOGERROR, "%s - Error, could not open file %s", __FUNCTION__, strFile.c_str());
  362. Dispose();
  363. return false;
  364. }
  365. }
  366. // set the interrupt callback, appeared in libavformat 53.15.0
  367. m_pFormatContext->interrupt_callback = int_cb;
  368. // analyse very short to speed up mjpeg playback start
  369. if (iformat && (strcmp(iformat->name, "mjpeg") == 0) && m_ioContext->seekable == 0)
  370. m_pFormatContext->max_analyze_duration = 500000;
  371. // we need to know if this is matroska or avi later
  372. m_bMatroska = strncmp(m_pFormatContext->iformat->name, "matroska", 8) == 0; // for "matroska.webm"
  373. m_bAVI = strcmp(m_pFormatContext->iformat->name, "avi") == 0;
  374. if (streaminfo)
  375. {
  376. /* too speed up dvd switches, only analyse very short */
  377. if(m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD))
  378. m_pFormatContext->max_analyze_duration = 500000;
  379. CLog::Log(LOGDEBUG, "%s - avformat_find_stream_info starting", __FUNCTION__);
  380. int iErr = m_dllAvFormat.avformat_find_stream_info(m_pFormatContext, NULL);
  381. if (iErr < 0)
  382. {
  383. CLog::Log(LOGWARNING,"could not find codec parameters for %s", strFile.c_str());
  384. if (m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD) || (m_pFormatContext->nb_streams == 1 && m_pFormatContext->streams[0]->codec->codec_id == CODEC_ID_AC3))
  385. {
  386. // special case, our codecs can still handle it.
  387. }
  388. else
  389. {
  390. Dispose();
  391. return false;
  392. }
  393. }
  394. CLog::Log(LOGDEBUG, "%s - av_find_stream_info finished", __FUNCTION__);
  395. }
  396. // reset any timeout
  397. m_timeout.SetInfinite();
  398. // if format can be nonblocking, let's use that
  399. m_pFormatContext->flags |= AVFMT_FLAG_NONBLOCK;
  400. // print some extra information
  401. m_dllAvFormat.av_dump_format(m_pFormatContext, 0, strFile.c_str(), 0);
  402. UpdateCurrentPTS();
  403. // add the ffmpeg streams to our own stream array
  404. if (m_pFormatContext->nb_programs)
  405. {
  406. // look for first non empty stream and discard nonselected programs
  407. for (unsigned int i = 0; i < m_pFormatContext->nb_programs; i++)
  408. {
  409. if(m_program == UINT_MAX && m_pFormatContext->programs[i]->nb_stream_indexes > 0)
  410. m_program = i;
  411. if(i != m_program)
  412. m_pFormatContext->programs[i]->discard = AVDISCARD_ALL;
  413. }
  414. if(m_program != UINT_MAX)
  415. {
  416. // add streams from selected program
  417. for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++)
  418. AddStream(m_pFormatContext->programs[m_program]->stream_index[i]);
  419. }
  420. }
  421. // if there were no programs or they were all empty, add all streams
  422. if (m_program == UINT_MAX)
  423. {
  424. for (unsigned int i = 0; i < m_pFormatContext->nb_streams; i++)
  425. AddStream(i);
  426. }
  427. return true;
  428. }
  429. void CDVDDemuxFFmpeg::Dispose()
  430. {
  431. g_demuxer.set(this);
  432. if (m_pFormatContext)
  433. {
  434. if (m_ioContext && m_pFormatContext->pb && m_pFormatContext->pb != m_ioContext)
  435. {
  436. CLog::Log(LOGWARNING, "CDVDDemuxFFmpeg::Dispose - demuxer changed our byte context behind our back, possible memleak");
  437. m_ioContext = m_pFormatContext->pb;
  438. }
  439. m_dllAvFormat.avformat_close_input(&m_pFormatContext);
  440. }
  441. if(m_ioContext)
  442. {
  443. m_dllAvUtil.av_free(m_ioContext->buffer);
  444. m_dllAvUtil.av_free(m_ioContext);
  445. }
  446. m_ioContext = NULL;
  447. m_pFormatContext = NULL;
  448. m_speed = DVD_PLAYSPEED_NORMAL;
  449. for (int i = 0; i < MAX_STREAMS; i++)
  450. {
  451. if (m_streams[i])
  452. {
  453. if (m_streams[i]->ExtraData)
  454. delete[] (BYTE*)(m_streams[i]->ExtraData);
  455. delete m_streams[i];
  456. }
  457. m_streams[i] = NULL;
  458. }
  459. m_pInput = NULL;
  460. m_dllAvFormat.Unload();
  461. m_dllAvCodec.Unload();
  462. m_dllAvUtil.Unload();
  463. }
  464. void CDVDDemuxFFmpeg::Reset()
  465. {
  466. CDVDInputStream* pInputStream = m_pInput;
  467. Dispose();
  468. Open(pInputStream);
  469. }
  470. void CDVDDemuxFFmpeg::Flush()
  471. {
  472. g_demuxer.set(this);
  473. // naughty usage of an internal ffmpeg function
  474. if (m_pFormatContext)
  475. m_dllAvFormat.av_read_frame_flush(m_pFormatContext);
  476. m_iCurrentPts = DVD_NOPTS_VALUE;
  477. }
  478. void CDVDDemuxFFmpeg::Abort()
  479. {
  480. m_timeout.SetExpired();
  481. }
  482. void CDVDDemuxFFmpeg::SetSpeed(int iSpeed)
  483. {
  484. g_demuxer.set(this);
  485. if(!m_pFormatContext)
  486. return;
  487. if(m_speed != DVD_PLAYSPEED_PAUSE && iSpeed == DVD_PLAYSPEED_PAUSE)
  488. {
  489. m_pInput->Pause((double)m_iCurrentPts);
  490. m_dllAvFormat.av_read_pause(m_pFormatContext);
  491. }
  492. else if(m_speed == DVD_PLAYSPEED_PAUSE && iSpeed != DVD_PLAYSPEED_PAUSE)
  493. {
  494. m_pInput->Pause((double)m_iCurrentPts);
  495. m_dllAvFormat.av_read_play(m_pFormatContext);
  496. }
  497. m_speed = iSpeed;
  498. AVDiscard discard = AVDISCARD_NONE;
  499. if(m_speed > 4*DVD_PLAYSPEED_NORMAL)
  500. discard = AVDISCARD_NONKEY;
  501. else if(m_speed > 2*DVD_PLAYSPEED_NORMAL)
  502. discard = AVDISCARD_BIDIR;
  503. else if(m_speed < DVD_PLAYSPEED_PAUSE)
  504. discard = AVDISCARD_NONKEY;
  505. for(unsigned int i = 0; i < m_pFormatContext->nb_streams; i++)
  506. {
  507. if(m_pFormatContext->streams[i])
  508. {
  509. if(m_pFormatContext->streams[i]->discard != AVDISCARD_ALL)
  510. m_pFormatContext->streams[i]->discard = discard;
  511. }
  512. }
  513. }
  514. double CDVDDemuxFFmpeg::ConvertTimestamp(int64_t pts, int den, int num)
  515. {
  516. if (pts == (int64_t)AV_NOPTS_VALUE)
  517. return DVD_NOPTS_VALUE;
  518. // do calculations in floats as they can easily overflow otherwise
  519. // we don't care for having a completly exact timestamp anyway
  520. double timestamp = (double)pts * num / den;
  521. double starttime = 0.0f;
  522. // for dvd's we need the original time
  523. if(dynamic_cast<CDVDInputStream::IMenus*>(m_pInput))
  524. starttime = dynamic_cast<CDVDInputStream::IMenus*>(m_pInput)->GetTimeStampCorrection() / DVD_TIME_BASE;
  525. else if (m_pFormatContext->start_time != (int64_t)AV_NOPTS_VALUE)
  526. starttime = (double)m_pFormatContext->start_time / AV_TIME_BASE;
  527. if(timestamp > starttime)
  528. timestamp -= starttime;
  529. else if( timestamp + 0.1f > starttime )
  530. timestamp = 0;
  531. return timestamp*DVD_TIME_BASE;
  532. }
  533. DemuxPacket* CDVDDemuxFFmpeg::Read()
  534. {
  535. g_demuxer.set(this);
  536. AVPacket pkt;
  537. DemuxPacket* pPacket = NULL;
  538. // on some cases where the received packet is invalid we will need to return an empty packet (0 length) otherwise the main loop (in CDVDPlayer)
  539. // would consider this the end of stream and stop.
  540. bool bReturnEmpty = false;
  541. { CSingleLock lock(m_critSection); // open lock scope
  542. if (m_pFormatContext)
  543. {
  544. // assume we are not eof
  545. if(m_pFormatContext->pb)
  546. m_pFormatContext->pb->eof_reached = 0;
  547. // keep track if ffmpeg doesn't always set these
  548. pkt.size = 0;
  549. pkt.data = NULL;
  550. pkt.stream_index = MAX_STREAMS;
  551. // timeout reads after 100ms
  552. m_timeout.Set(20000);
  553. int result = m_dllAvFormat.av_read_frame(m_pFormatContext, &pkt);
  554. m_timeout.SetInfinite();
  555. if (result == AVERROR(EINTR) || result == AVERROR(EAGAIN))
  556. {
  557. // timeout, probably no real error, return empty packet
  558. bReturnEmpty = true;
  559. }
  560. else if (result < 0)
  561. {
  562. Flush();
  563. }
  564. else if (pkt.size < 0 || pkt.stream_index >= MAX_STREAMS)
  565. {
  566. // XXX, in some cases ffmpeg returns a negative packet size
  567. if(m_pFormatContext->pb && !m_pFormatContext->pb->eof_reached)
  568. {
  569. CLog::Log(LOGERROR, "CDVDDemuxFFmpeg::Read() no valid packet");
  570. bReturnEmpty = true;
  571. Flush();
  572. }
  573. else
  574. CLog::Log(LOGERROR, "CDVDDemuxFFmpeg::Read() returned invalid packet and eof reached");
  575. m_dllAvCodec.av_free_packet(&pkt);
  576. }
  577. else
  578. {
  579. AVStream *stream = m_pFormatContext->streams[pkt.stream_index];
  580. if (m_program != UINT_MAX)
  581. {
  582. /* check so packet belongs to selected program */
  583. for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++)
  584. {
  585. if(pkt.stream_index == (int)m_pFormatContext->programs[m_program]->stream_index[i])
  586. {
  587. pPacket = CDVDDemuxUtils::AllocateDemuxPacket(pkt.size);
  588. break;
  589. }
  590. }
  591. if (!pPacket)
  592. bReturnEmpty = true;
  593. }
  594. else
  595. pPacket = CDVDDemuxUtils::AllocateDemuxPacket(pkt.size);
  596. if (pPacket)
  597. {
  598. // lavf sometimes bugs out and gives 0 dts/pts instead of no dts/pts
  599. // since this could only happens on initial frame under normal
  600. // circomstances, let's assume it is wrong all the time
  601. if(pkt.dts == 0)
  602. pkt.dts = AV_NOPTS_VALUE;
  603. if(pkt.pts == 0)
  604. pkt.pts = AV_NOPTS_VALUE;
  605. if(m_bMatroska && stream->codec && stream->codec->codec_type == AVMEDIA_TYPE_VIDEO)
  606. { // matroska can store different timestamps
  607. // for different formats, for native stored
  608. // stuff it is pts, but for ms compatibility
  609. // tracks, it is really dts. sadly ffmpeg
  610. // sets these two timestamps equal all the
  611. // time, so we select it here instead
  612. if(stream->codec->codec_tag == 0)
  613. pkt.dts = AV_NOPTS_VALUE;
  614. else
  615. pkt.pts = AV_NOPTS_VALUE;
  616. }
  617. // we need to get duration slightly different for matroska embedded text subtitels
  618. if(m_bMatroska && stream->codec->codec_id == CODEC_ID_TEXT && pkt.convergence_duration != 0)
  619. pkt.duration = pkt.convergence_duration;
  620. if(m_bAVI && stream->codec && stream->codec->codec_type == AVMEDIA_TYPE_VIDEO)
  621. {
  622. // AVI's always have borked pts, specially if m_pFormatContext->flags includes
  623. // AVFMT_FLAG_GENPTS so always use dts
  624. pkt.pts = AV_NOPTS_VALUE;
  625. }
  626. // copy contents into our own packet
  627. pPacket->iSize = pkt.size;
  628. // maybe we can avoid a memcpy here by detecting where pkt.destruct is pointing too?
  629. if (pkt.data)
  630. memcpy(pPacket->pData, pkt.data, pPacket->iSize);
  631. pPacket->pts = ConvertTimestamp(pkt.pts, stream->time_base.den, stream->time_base.num);
  632. pPacket->dts = ConvertTimestamp(pkt.dts, stream->time_base.den, stream->time_base.num);
  633. pPacket->duration = DVD_SEC_TO_TIME((double)pkt.duration * stream->time_base.num / stream->time_base.den);
  634. // used to guess streamlength
  635. if (pPacket->dts != DVD_NOPTS_VALUE && (pPacket->dts > m_iCurrentPts || m_iCurrentPts == DVD_NOPTS_VALUE))
  636. m_iCurrentPts = pPacket->dts;
  637. // check if stream has passed full duration, needed for live streams
  638. if(pkt.dts != (int64_t)AV_NOPTS_VALUE)
  639. {
  640. int64_t duration;
  641. duration = pkt.dts;
  642. if(stream->start_time != (int64_t)AV_NOPTS_VALUE)
  643. duration -= stream->start_time;
  644. if(duration > stream->duration)
  645. {
  646. stream->duration = duration;
  647. duration = m_dllAvUtil.av_rescale_rnd(stream->duration, (int64_t)stream->time_base.num * AV_TIME_BASE, stream->time_base.den, AV_ROUND_NEAR_INF);
  648. if ((m_pFormatContext->duration == (int64_t)AV_NOPTS_VALUE)
  649. || (m_pFormatContext->duration != (int64_t)AV_NOPTS_VALUE && duration > m_pFormatContext->duration))
  650. m_pFormatContext->duration = duration;
  651. }
  652. }
  653. pPacket->iStreamId = pkt.stream_index; // XXX just for now
  654. }
  655. m_dllAvCodec.av_free_packet(&pkt);
  656. }
  657. }
  658. } // end of lock scope
  659. if (bReturnEmpty && !pPacket)
  660. pPacket = CDVDDemuxUtils::AllocateDemuxPacket(0);
  661. if (!pPacket) return NULL;
  662. // check streams, can we make this a bit more simple?
  663. if (pPacket && pPacket->iStreamId >= 0 && pPacket->iStreamId <= MAX_STREAMS)
  664. {
  665. if (!m_streams[pPacket->iStreamId] ||
  666. m_streams[pPacket->iStreamId]->pPrivate != m_pFormatContext->streams[pPacket->iStreamId] ||
  667. m_streams[pPacket->iStreamId]->codec != m_pFormatContext->streams[pPacket->iStreamId]->codec->codec_id)
  668. {
  669. // content has changed, or stream did not yet exist
  670. AddStream(pPacket->iStreamId);
  671. }
  672. // we already check for a valid m_streams[pPacket->iStreamId] above
  673. else if (m_streams[pPacket->iStreamId]->type == STREAM_AUDIO)
  674. {
  675. if (((CDemuxStreamAudio*)m_streams[pPacket->iStreamId])->iChannels != m_pFormatContext->streams[pPacket->iStreamId]->codec->channels ||
  676. ((CDemuxStreamAudio*)m_streams[pPacket->iStreamId])->iSampleRate != m_pFormatContext->streams[pPacket->iStreamId]->codec->sample_rate)
  677. {
  678. // content has changed
  679. AddStream(pPacket->iStreamId);
  680. }
  681. }
  682. else if (m_streams[pPacket->iStreamId]->type == STREAM_VIDEO)
  683. {
  684. if (((CDemuxStreamVideo*)m_streams[pPacket->iStreamId])->iWidth != m_pFormatContext->streams[pPacket->iStreamId]->codec->width ||
  685. ((CDemuxStreamVideo*)m_streams[pPacket->iStreamId])->iHeight != m_pFormatContext->streams[pPacket->iStreamId]->codec->height)
  686. {
  687. // content has changed
  688. AddStream(pPacket->iStreamId);
  689. }
  690. }
  691. }
  692. return pPacket;
  693. }
  694. bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts)
  695. {
  696. g_demuxer.set(this);
  697. if(time < 0)
  698. time = 0;
  699. CDVDInputStream::ISeekTime* ist = dynamic_cast<CDVDInputStream::ISeekTime*>(m_pInput);
  700. if (ist)
  701. {
  702. if (!ist->SeekTime(time))
  703. return false;
  704. if(startpts)
  705. *startpts = DVD_NOPTS_VALUE;
  706. Flush();
  707. // also empty the internal ffmpeg buffer
  708. m_ioContext->buf_ptr = m_ioContext->buf_end;
  709. return true;
  710. }
  711. if(!m_pInput->Seek(0, SEEK_POSSIBLE)
  712. && !m_pInput->IsStreamType(DVDSTREAM_TYPE_FFMPEG))
  713. {
  714. CLog::Log(LOGDEBUG, "%s - input stream reports it is not seekable", __FUNCTION__);
  715. return false;
  716. }
  717. int64_t seek_pts = (int64_t)time * (AV_TIME_BASE / 1000);
  718. if (m_pFormatContext->start_time != (int64_t)AV_NOPTS_VALUE)
  719. seek_pts += m_pFormatContext->start_time;
  720. int ret;
  721. {
  722. CSingleLock lock(m_critSection);
  723. ret = m_dllAvFormat.av_seek_frame(m_pFormatContext, -1, seek_pts, backwords ? AVSEEK_FLAG_BACKWARD : 0);
  724. if(ret >= 0)
  725. UpdateCurrentPTS();
  726. }
  727. if(m_iCurrentPts == DVD_NOPTS_VALUE)
  728. CLog::Log(LOGDEBUG, "%s - unknown position after seek", __FUNCTION__);
  729. else
  730. CLog::Log(LOGDEBUG, "%s - seek ended up on time %d", __FUNCTION__, (int)(m_iCurrentPts / DVD_TIME_BASE * 1000));
  731. // in this case the start time is requested time
  732. if(startpts)
  733. *startpts = DVD_MSEC_TO_TIME(time);
  734. // demuxer will return failure, if you seek to eof
  735. if (m_pInput->IsEOF() && ret <= 0)
  736. return true;
  737. return (ret >= 0);
  738. }
  739. bool CDVDDemuxFFmpeg::SeekByte(int64_t pos)
  740. {
  741. g_demuxer.set(this);
  742. CSingleLock lock(m_critSection);
  743. int ret = m_dllAvFormat.av_seek_frame(m_pFormatContext, -1, pos, AVSEEK_FLAG_BYTE);
  744. if(ret >= 0)
  745. UpdateCurrentPTS();
  746. return (ret >= 0);
  747. }
  748. void CDVDDemuxFFmpeg::UpdateCurrentPTS()
  749. {
  750. m_iCurrentPts = DVD_NOPTS_VALUE;
  751. for(unsigned int i = 0; i < m_pFormatContext->nb_streams; i++)
  752. {
  753. AVStream *stream = m_pFormatContext->streams[i];
  754. if(stream && stream->cur_dts != (int64_t)AV_NOPTS_VALUE)
  755. {
  756. double ts = ConvertTimestamp(stream->cur_dts, stream->time_base.den, stream->time_base.num);
  757. if(m_iCurrentPts == DVD_NOPTS_VALUE || m_iCurrentPts > ts )
  758. m_iCurrentPts = ts;
  759. }
  760. }
  761. }
  762. int CDVDDemuxFFmpeg::GetStreamLength()
  763. {
  764. if (!m_pFormatContext)
  765. return 0;
  766. return (int)(m_pFormatContext->duration / (AV_TIME_BASE / 1000));
  767. }
  768. CDemuxStream* CDVDDemuxFFmpeg::GetStream(int iStreamId)
  769. {
  770. if (iStreamId < 0 || iStreamId >= MAX_STREAMS) return NULL;
  771. return m_streams[iStreamId];
  772. }
  773. int CDVDDemuxFFmpeg::GetNrOfStreams()
  774. {
  775. int i = 0;
  776. while (i < MAX_STREAMS && m_streams[i]) i++;
  777. return i;
  778. }
  779. static double SelectAspect(AVStream* st, bool* forced)
  780. {
  781. *forced = false;
  782. /* if stream aspect is 1:1 or 0:0 use codec aspect */
  783. if((st->sample_aspect_ratio.den == 1 || st->sample_aspect_ratio.den == 0)
  784. && (st->sample_aspect_ratio.num == 1 || st->sample_aspect_ratio.num == 0)
  785. && st->codec->sample_aspect_ratio.num != 0)
  786. return av_q2d(st->codec->sample_aspect_ratio);
  787. *forced = true;
  788. if(st->sample_aspect_ratio.num != 0)
  789. return av_q2d(st->sample_aspect_ratio);
  790. return 0.0;
  791. }
  792. void CDVDDemuxFFmpeg::AddStream(int iId)
  793. {
  794. if(iId >= MAX_STREAMS)
  795. {
  796. CLog::Log(LOGWARNING, "%s - streams id %d exeeds maximum supported", __FUNCTION__, iId);
  797. return;
  798. }
  799. AVStream* pStream = m_pFormatContext->streams[iId];
  800. if (pStream)
  801. {
  802. CDemuxStream* old = m_streams[iId];
  803. switch (pStream->codec->codec_type)
  804. {
  805. case AVMEDIA_TYPE_AUDIO:
  806. {
  807. CDemuxStreamAudioFFmpeg* st = new CDemuxStreamAudioFFmpeg(this, pStream);
  808. m_streams[iId] = st;
  809. st->iChannels = pStream->codec->channels;
  810. st->iSampleRate = pStream->codec->sample_rate;
  811. st->iBlockAlign = pStream->codec->block_align;
  812. st->iBitRate = pStream->codec->bit_rate;
  813. st->iBitsPerSample = pStream->codec->bits_per_coded_sample;
  814. if(m_dllAvUtil.av_dict_get(pStream->metadata, "title", NULL, 0))
  815. st->m_description = m_dllAvUtil.av_dict_get(pStream->metadata, "title", NULL, 0)->value;
  816. break;
  817. }
  818. case AVMEDIA_TYPE_VIDEO:
  819. {
  820. CDemuxStreamVideoFFmpeg* st = new CDemuxStreamVideoFFmpeg(this, pStream);
  821. m_streams[iId] = st;
  822. if(strcmp(m_pFormatContext->iformat->name, "flv") == 0)
  823. st->bVFR = true;
  824. else
  825. st->bVFR = false;
  826. // never trust pts in avi files with h264.
  827. if (m_bAVI && pStream->codec->codec_id == CODEC_ID_H264)
  828. st->bPTSInvalid = true;
  829. //average fps is more accurate for mkv files
  830. if (m_bMatroska && pStream->avg_frame_rate.den && pStream->avg_frame_rate.num)
  831. {
  832. st->iFpsRate = pStream->avg_frame_rate.num;
  833. st->iFpsScale = pStream->avg_frame_rate.den;
  834. }
  835. else if(pStream->r_frame_rate.den && pStream->r_frame_rate.num)
  836. {
  837. st->iFpsRate = pStream->r_frame_rate.num;
  838. st->iFpsScale = pStream->r_frame_rate.den;
  839. }
  840. else
  841. {
  842. st->iFpsRate = 0;
  843. st->iFpsScale = 0;
  844. }
  845. if (pStream->codec_info_nb_frames > 0
  846. && pStream->codec_info_nb_frames <= 2
  847. && m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD))
  848. {
  849. CLog::Log(LOGDEBUG, "%s - fps may be unreliable since ffmpeg decoded only %d frame(s)", __FUNCTION__, pStream->codec_info_nb_frames);
  850. st->iFpsRate = 0;
  851. st->iFpsScale = 0;
  852. }
  853. st->iWidth = pStream->codec->width;
  854. st->iHeight = pStream->codec->height;
  855. st->fAspect = SelectAspect(pStream, &st->bForcedAspect) * pStream->codec->width / pStream->codec->height;
  856. st->iLevel = pStream->codec->level;
  857. st->iProfile = pStream->codec->profile;
  858. st->iOrientation = 0;
  859. AVDictionaryEntry *rtag = m_dllAvUtil.av_dict_get(pStream->metadata, "rotate", NULL, 0);
  860. if (rtag)
  861. st->iOrientation = atoi(rtag->value);
  862. if ( m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD) )
  863. {
  864. if (pStream->codec->codec_id == CODEC_ID_PROBE)
  865. {
  866. // fix MPEG-1/MPEG-2 video stream probe returning CODEC_ID_PROBE for still frames.
  867. // ffmpeg issue 1871, regression from ffmpeg r22831.
  868. if ((pStream->id & 0xF0) == 0xE0)
  869. {
  870. pStream->codec->codec_id = CODEC_ID_MPEG2VIDEO;
  871. pStream->codec->codec_tag = MKTAG('M','P','2','V');
  872. CLog::Log(LOGERROR, "%s - CODEC_ID_PROBE detected, forcing CODEC_ID_MPEG2VIDEO", __FUNCTION__);
  873. }
  874. }
  875. }
  876. break;
  877. }
  878. case AVMEDIA_TYPE_DATA:
  879. {
  880. m_streams[iId] = new CDemuxStream();
  881. m_streams[iId]->type = STREAM_DATA;
  882. break;
  883. }
  884. case AVMEDIA_TYPE_SUBTITLE:
  885. {
  886. #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52,38,1)
  887. if (pStream->codec->codec_id == CODEC_ID_DVB_TELETEXT && g_guiSettings.GetBool("videoplayer.teletextenabled"))
  888. {
  889. CDemuxStreamTeletext* st = new CDemuxStreamTeletext();
  890. m_streams[iId] = st;
  891. m_streams[iId]->type = STREAM_TELETEXT;
  892. break;
  893. }
  894. else
  895. #endif
  896. {
  897. CDemuxStreamSubtitleFFmpeg* st = new CDemuxStreamSubtitleFFmpeg(this, pStream);
  898. m_streams[iId] = st;
  899. if(pStream->codec)
  900. st->identifier = pStream->codec->sub_id;
  901. if(m_dllAvUtil.av_dict_get(pStream->metadata, "title", NULL, 0))
  902. st->m_description = m_dllAvUtil.av_dict_get(pStream->metadata, "title", NULL, 0)->value;
  903. break;
  904. }
  905. }
  906. case AVMEDIA_TYPE_ATTACHMENT:
  907. { //mkv attachments. Only bothering with fonts for now.
  908. if(pStream->codec->codec_id == CODEC_ID_TTF)
  909. {
  910. std::string fileName = "special://temp/fonts/";
  911. XFILE::CDirectory::Create(fileName);
  912. AVDictionaryEntry *nameTag = m_dllAvUtil.av_dict_get(pStream->metadata, "filename", NULL, 0);
  913. if (!nameTag) {
  914. CLog::Log(LOGERROR, "%s: TTF attachment has no name", __FUNCTION__);
  915. break;
  916. }
  917. fileName += nameTag->value;
  918. XFILE::CFile file;
  919. if(pStream->codec->extradata && file.OpenForWrite(fileName))
  920. {
  921. file.Write(pStream->codec->extradata, pStream->codec->extradata_size);
  922. file.Close();
  923. }
  924. }
  925. m_streams[iId] = new CDemuxStream();
  926. m_streams[iId]->type = STREAM_NONE;
  927. break;
  928. }
  929. default:
  930. {
  931. m_streams[iId] = new CDemuxStream();
  932. m_streams[iId]->type = STREAM_NONE;
  933. break;
  934. }
  935. }
  936. // delete old stream after new is created
  937. // since dvdplayer uses the pointer to know
  938. // if something changed in the demuxer
  939. if (old)
  940. {
  941. if( old->ExtraData ) delete[] (BYTE*)(old->ExtraData);
  942. delete old;
  943. }
  944. // generic stuff
  945. if (pStream->duration != (int64_t)AV_NOPTS_VALUE) m_streams[iId]->iDuration = (int)((pStream->duration / AV_TIME_BASE) & 0xFFFFFFFF);
  946. m_streams[iId]->codec = pStream->codec->codec_id;
  947. m_streams[iId]->codec_fourcc = pStream->codec->codec_tag;
  948. m_streams[iId]->profile = pStream->codec->profile;
  949. m_streams[iId]->iId = iId;
  950. m_streams[iId]->source = STREAM_SOURCE_DEMUX;
  951. m_streams[iId]->pPrivate = pStream;
  952. m_streams[iId]->flags = (CDemuxStream::EFlags)pStream->disposition;
  953. #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52,83,0)
  954. // API added on: 2010-10-15
  955. // (Note that while the function was available earlier, the generic
  956. // metadata tags were not populated by default)
  957. AVDictionaryEntry *langTag = m_dllAvUtil.av_dict_get(pStream->metadata, "language", NULL, 0);
  958. if (langTag)
  959. strncpy(m_streams[iId]->language, langTag->value, 3);
  960. #else
  961. strcpy( m_streams[iId]->language, pStream->language );
  962. #endif
  963. if( pStream->codec->extradata && pStream->codec->extradata_size > 0 )
  964. {
  965. m_streams[iId]->ExtraSize = pStream->codec->extradata_size;
  966. m_streams[iId]->ExtraData = new BYTE[pStream->codec->extradata_size];
  967. memcpy(m_streams[iId]->ExtraData, pStream->codec->extradata, pStream->codec->extradata_size);
  968. }
  969. #ifdef HAVE_LIBBLURAY
  970. if( m_pInput->IsStreamType(DVDSTREAM_TYPE_BLURAY) )
  971. static_cast<CDVDInputStreamBluray*>(m_pInput)->GetStreamInfo(pStream->id, m_streams[iId]->language);
  972. #endif
  973. if( m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD) )
  974. {
  975. // this stuff is really only valid for dvd's.
  976. // this is so that the physicalid matches the
  977. // id's reported from libdvdnav
  978. switch(m_streams[iId]->codec)
  979. {
  980. case CODEC_ID_AC3:
  981. m_streams[iId]->iPhysicalId = pStream->id - 128;
  982. break;
  983. case CODEC_ID_DTS:
  984. m_streams[iId]->iPhysicalId = pStream->id - 136;
  985. break;
  986. case CODEC_ID_MP2:
  987. m_streams[iId]->iPhysicalId = pStream->id - 448;
  988. break;
  989. case CODEC_ID_PCM_S16BE:
  990. m_streams[iId]->iPhysicalId = pStream->id - 160;
  991. break;
  992. case CODEC_ID_DVD_SUBTITLE:
  993. m_streams[iId]->iPhysicalId = pStream->id - 0x20;
  994. break;
  995. default:
  996. m_streams[iId]->iPhysicalId = pStream->id & 0x1f;
  997. break;
  998. }
  999. }
  1000. else
  1001. m_streams[iId]->iPhysicalId = pStream->id;
  1002. }
  1003. }
  1004. std::string CDVDDemuxFFmpeg::GetFileName()
  1005. {
  1006. if(m_pInput)
  1007. return m_pInput->GetFileName();
  1008. else
  1009. return "";
  1010. }
  1011. int CDVDDemuxFFmpeg::GetChapterCount()
  1012. {
  1013. CDVDInputStream::IChapter* ich = dynamic_cast<CDVDInputStream::IChapter*>(m_pInput);
  1014. if(ich)
  1015. return ich->GetChapterCount();
  1016. if(m_pFormatContext == NULL)
  1017. return 0;
  1018. #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52,14,0)
  1019. return m_pFormatContext->nb_chapters;
  1020. #else
  1021. return 0;
  1022. #endif
  1023. }
  1024. int CDVDDemuxFFmpeg::GetChapter()
  1025. {
  1026. CDVDInputStream::IChapter* ich = dynamic_cast<CDVDInputStream::IChapter*>(m_pInput);
  1027. if(ich)
  1028. return ich->GetChapter();
  1029. if(m_pFormatContext == NULL
  1030. || m_iCurrentPts == DVD_NOPTS_VALUE)
  1031. return 0;
  1032. #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52,14,0)
  1033. for(unsigned i = 0; i < m_pFormatContext->nb_chapters; i++)
  1034. {
  1035. AVChapter *chapter = m_pFormatContext->chapters[i];
  1036. if(m_iCurrentPts >= ConvertTimestamp(chapter->start, chapter->time_base.den, chapter->time_base.num)
  1037. && m_iCurrentPts < ConvertTimestamp(chapter->end, chapter->time_base.den, chapter->time_base.num))
  1038. return i + 1;
  1039. }
  1040. #endif
  1041. return 0;
  1042. }
  1043. void CDVDDemuxFFmpeg::GetChapterName(std::string& strChapterName)
  1044. {
  1045. CDVDInputStream::IChapter* ich = dynamic_cast<CDVDInputStream::IChapter*>(m_pInput);
  1046. if(ich)
  1047. ich->GetChapterName(strChapterName);
  1048. else
  1049. {
  1050. #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52,14,0)
  1051. int chapterIdx = GetChapter();
  1052. if(chapterIdx <= 0)
  1053. return;
  1054. #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52,83,0)
  1055. // API added on: 2010-10-15
  1056. // (Note that while the function was available earlier, the generic
  1057. // metadata tags were not populated by default)
  1058. AVDictionaryEntry *titleTag = m_dllAvUtil.av_dict_get(m_pFormatContext->chapters[chapterIdx-1]->metadata,
  1059. "title", NULL, 0);
  1060. if (titleTag)
  1061. strChapterName = titleTag->value;
  1062. #else
  1063. if (m_pFormatContext->chapters[chapterIdx-1]->title)
  1064. strChapterName = m_pFormatContext->chapters[chapterIdx-1]->title;
  1065. #endif
  1066. #endif
  1067. }
  1068. }
  1069. bool CDVDDemuxFFmpeg::SeekChapter(int chapter, double* startpts)
  1070. {
  1071. if(chapter < 1)
  1072. chapter = 1;
  1073. CDVDInputStream::IChapter* ich = dynamic_cast<CDVDInputStream::IChapter*>(m_pInput);
  1074. if(ich)
  1075. {
  1076. CLog::Log(LOGDEBUG, "%s - chapter seeking using input stream", __FUNCTION__);
  1077. if(!ich->SeekChapter(chapter))
  1078. return false;
  1079. if(startpts)
  1080. *startpts = DVD_NOPTS_VALUE;
  1081. Flush();
  1082. return true;
  1083. }
  1084. if(m_pFormatContext == NULL)
  1085. return false;
  1086. #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52,14,0)
  1087. if(chapter < 1 || chapter > (int)m_pFormatContext->nb_chapters)
  1088. return false;
  1089. AVChapter *ch = m_pFormatContext->chapters[chapter-1];
  1090. double dts = ConvertTimestamp(ch->start, ch->time_base.den, ch->time_base.num);
  1091. return SeekTime(DVD_TIME_TO_MSEC(dts), true, startpts);
  1092. #else
  1093. return false;
  1094. #endif
  1095. }
  1096. void CDVDDemuxFFmpeg::GetStreamCodecName(int iStreamId, CStdString &strName)
  1097. {
  1098. CDemuxStream *stream = GetStream(iStreamId);
  1099. if (stream)
  1100. {
  1101. unsigned int in = stream->codec_fourcc;
  1102. // FourCC codes are only valid on video streams, audio codecs in AVI/WAV
  1103. // are 2 bytes and audio codecs in transport streams have subtle variation
  1104. // e.g AC-3 instead of ac3
  1105. if (stream->type == STREAM_VIDEO && in != 0)
  1106. {
  1107. char fourcc[5];
  1108. #if defined(__powerpc__)
  1109. fourcc[0] = in & 0xff;
  1110. fourcc[1] = (in >> 8) & 0xff;
  1111. fourcc[2] = (in >> 16) & 0xff;
  1112. fourcc[3] = (in >> 24) & 0xff;
  1113. #else
  1114. memcpy(fourcc, &in, 4);
  1115. #endif
  1116. fourcc[4] = 0;
  1117. // fourccs have to be 4 characters
  1118. if (strlen(fourcc) == 4)
  1119. {
  1120. strName = fourcc;
  1121. strName.MakeLower();
  1122. return;
  1123. }
  1124. }
  1125. #ifdef FF_PROFILE_DTS_HD_MA
  1126. /* use profile to determine the DTS type */
  1127. if (stream->codec == CODEC_ID_DTS)
  1128. {
  1129. if (stream->profile == FF_PROFILE_DTS_HD_MA)
  1130. strName = "dtshd_ma";
  1131. else if (stream->profile == FF_PROFILE_DTS_HD_HRA)
  1132. strName = "dtshd_hra";
  1133. else
  1134. strName = "dca";
  1135. return;
  1136. }
  1137. #endif
  1138. AVCodec *codec = m_dllAvCodec.avcodec_find_decoder(stream->codec);
  1139. if (codec)
  1140. strName = codec->name;
  1141. }
  1142. }