summaryrefslogtreecommitdiffstats
path: root/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp')
-rw-r--r--xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp1767
1 files changed, 0 insertions, 1767 deletions
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
deleted file mode 100644
index f58472f..0000000
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
+++ /dev/null
@@ -1,1767 +0,0 @@
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 "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 TARGET_POSIX
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 "DVDInputStreams/DVDInputStreamPVRManager.h"
38#include "DVDInputStreams/DVDInputStreamFFmpeg.h"
39#include "DVDDemuxUtils.h"
40#include "DVDClock.h" // for DVD_TIME_BASE
41#include "commons/Exception.h"
42#include "settings/AdvancedSettings.h"
43#include "settings/Settings.h"
44#include "filesystem/File.h"
45#include "filesystem/CurlFile.h"
46#include "filesystem/Directory.h"
47#include "utils/log.h"
48#include "threads/Thread.h"
49#include "threads/SystemClock.h"
50#include "utils/TimeUtils.h"
51#include "utils/StringUtils.h"
52#include "URL.h"
53#include "cores/FFmpeg.h"
54
55extern "C" {
56#include "libavutil/opt.h"
57}
58
59struct StereoModeConversionMap
60{
61 const char* name;
62 const char* mode;
63};
64
65// we internally use the matroska string representation of stereoscopic modes.
66// This struct is a conversion map to convert stereoscopic mode values
67// from asf/wmv to the internally used matroska ones
68static const struct StereoModeConversionMap WmvToInternalStereoModeMap[] =
69{
70 { "SideBySideRF", "right_left" },
71 { "SideBySideLF", "left_right" },
72 { "OverUnderRT", "bottom_top" },
73 { "OverUnderLT", "top_bottom" },
74 {}
75};
76
77#define FF_MAX_EXTRADATA_SIZE ((1 << 28) - FF_INPUT_BUFFER_PADDING_SIZE)
78
79void CDemuxStreamAudioFFmpeg::GetStreamInfo(std::string& strInfo)
80{
81 if(!m_stream) return;
82 char temp[128];
83 avcodec_string(temp, 128, m_stream->codec, 0);
84 strInfo = temp;
85}
86
87void CDemuxStreamAudioFFmpeg::GetStreamName(std::string& strInfo)
88{
89 if(!m_stream) return;
90 if(!m_description.empty())
91 strInfo = m_description;
92 else
93 CDemuxStream::GetStreamName(strInfo);
94}
95
96void CDemuxStreamSubtitleFFmpeg::GetStreamName(std::string& strInfo)
97{
98 if(!m_stream) return;
99 if(!m_description.empty())
100 strInfo = m_description;
101 else
102 CDemuxStream::GetStreamName(strInfo);
103}
104
105void CDemuxStreamVideoFFmpeg::GetStreamInfo(std::string& strInfo)
106{
107 if(!m_stream) return;
108 char temp[128];
109 avcodec_string(temp, 128, m_stream->codec, 0);
110 strInfo = temp;
111}
112
113void CDemuxStreamSubtitleFFmpeg::GetStreamInfo(std::string& strInfo)
114{
115 if(!m_stream) return;
116 char temp[128];
117 avcodec_string(temp, 128, m_stream->codec, 0);
118 strInfo = temp;
119}
120
121static int interrupt_cb(void* ctx)
122{
123 CDVDDemuxFFmpeg* demuxer = static_cast<CDVDDemuxFFmpeg*>(ctx);
124 if(demuxer && demuxer->Aborted())
125 return 1;
126 return 0;
127}
128
129
130////////////////////////////////////////////////////////////////////////////////////////////////
131////////////////////////////////////////////////////////////////////////////////////////////////
132/*
133static int dvd_file_open(URLContext *h, const char *filename, int flags)
134{
135 return -1;
136}
137*/
138
139static int dvd_file_read(void *h, uint8_t* buf, int size)
140{
141 if(interrupt_cb(h))
142 return AVERROR_EXIT;
143
144 CDVDInputStream* pInputStream = static_cast<CDVDDemuxFFmpeg*>(h)->m_pInput;
145 return pInputStream->Read(buf, size);
146}
147/*
148static int dvd_file_write(URLContext *h, uint8_t* buf, int size)
149{
150 return -1;
151}
152*/
153static int64_t dvd_file_seek(void *h, int64_t pos, int whence)
154{
155 if(interrupt_cb(h))
156 return AVERROR_EXIT;
157
158 CDVDInputStream* pInputStream = static_cast<CDVDDemuxFFmpeg*>(h)->m_pInput;
159 if(whence == AVSEEK_SIZE)
160 return pInputStream->GetLength();
161 else
162 return pInputStream->Seek(pos, whence & ~AVSEEK_FORCE);
163}
164
165////////////////////////////////////////////////////////////////////////////////////////////////
166////////////////////////////////////////////////////////////////////////////////////////////////
167
168CDVDDemuxFFmpeg::CDVDDemuxFFmpeg() : CDVDDemux()
169{
170 m_pFormatContext = NULL;
171 m_pInput = NULL;
172 m_ioContext = NULL;
173 m_currentPts = DVD_NOPTS_VALUE;
174 m_bMatroska = false;
175 m_bAVI = false;
176 m_speed = DVD_PLAYSPEED_NORMAL;
177 m_program = UINT_MAX;
178 m_pkt.result = -1;
179 memset(&m_pkt.pkt, 0, sizeof(AVPacket));
180 m_streaminfo = true; /* set to true if we want to look for streams before playback */
181 m_checkvideo = false;
182}
183
184CDVDDemuxFFmpeg::~CDVDDemuxFFmpeg()
185{
186 Dispose();
187 ff_flush_avutil_log_buffers();
188}
189
190bool CDVDDemuxFFmpeg::Aborted()
191{
192 if(m_timeout.IsTimePast())
193 return true;
194
195 CDVDInputStreamFFmpeg * input = dynamic_cast<CDVDInputStreamFFmpeg*>(m_pInput);
196 if(input && input->Aborted())
197 return true;
198
199 return false;
200}
201
202bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput, bool streaminfo, bool fileinfo)
203{
204 AVInputFormat* iformat = NULL;
205 std::string strFile;
206 m_streaminfo = streaminfo;
207 m_currentPts = DVD_NOPTS_VALUE;
208 m_speed = DVD_PLAYSPEED_NORMAL;
209 m_program = UINT_MAX;
210 const AVIOInterruptCB int_cb = { interrupt_cb, this };
211
212 if (!pInput) return false;
213
214 m_pInput = pInput;
215 strFile = m_pInput->GetFileName();
216
217 if( m_pInput->GetContent().length() > 0 )
218 {
219 std::string content = m_pInput->GetContent();
220 StringUtils::ToLower(content);
221
222 /* check if we can get a hint from content */
223 if ( content.compare("video/x-vobsub") == 0 )
224 iformat = av_find_input_format("mpeg");
225 else if( content.compare("video/x-dvd-mpeg") == 0 )
226 iformat = av_find_input_format("mpeg");
227 else if( content.compare("video/mp2t") == 0 )
228 iformat = av_find_input_format("mpegts");
229 else if( content.compare("multipart/x-mixed-replace") == 0 )
230 iformat = av_find_input_format("mjpeg");
231 }
232
233 // open the demuxer
234 m_pFormatContext = avformat_alloc_context();
235 m_pFormatContext->interrupt_callback = int_cb;
236
237 // try to abort after 30 seconds
238 m_timeout.Set(30000);
239
240 if( m_pInput->IsStreamType(DVDSTREAM_TYPE_FFMPEG) )
241 {
242 // special stream type that makes avformat handle file opening
243 // allows internal ffmpeg protocols to be used
244 CURL url = m_pInput->GetURL();
245
246 AVDictionary *options = GetFFMpegOptionsFromURL(url);
247
248 int result=-1;
249 if (url.IsProtocol("mms"))
250 {
251 // try mmsh, then mmst
252 url.SetProtocol("mmsh");
253 url.SetProtocolOptions("");
254 result = avformat_open_input(&m_pFormatContext, url.Get().c_str(), iformat, &options);
255 if (result < 0)
256 {
257 url.SetProtocol("mmst");
258 strFile = url.Get();
259 }
260 }
261 if (result < 0 && avformat_open_input(&m_pFormatContext, strFile.c_str(), iformat, &options) < 0 )
262 {
263 CLog::Log(LOGDEBUG, "Error, could not open file %s", CURL::GetRedacted(strFile).c_str());
264 Dispose();
265 av_dict_free(&options);
266 return false;
267 }
268 av_dict_free(&options);
269 }
270 else
271 {
272 unsigned char* buffer = (unsigned char*)av_malloc(FFMPEG_FILE_BUFFER_SIZE);
273 m_ioContext = avio_alloc_context(buffer, FFMPEG_FILE_BUFFER_SIZE, 0, this, dvd_file_read, NULL, dvd_file_seek);
274 m_ioContext->max_packet_size = m_pInput->GetBlockSize();
275 if(m_ioContext->max_packet_size)
276 m_ioContext->max_packet_size *= FFMPEG_FILE_BUFFER_SIZE / m_ioContext->max_packet_size;
277
278 if(m_pInput->Seek(0, SEEK_POSSIBLE) == 0)
279 m_ioContext->seekable = 0;
280
281 std::string content = m_pInput->GetContent();
282 StringUtils::ToLower(content);
283 if (StringUtils::StartsWith(content, "audio/l16"))
284 iformat = av_find_input_format("s16be");
285
286 if( iformat == NULL )
287 {
288 // let ffmpeg decide which demuxer we have to open
289
290 bool trySPDIFonly = (m_pInput->GetContent() == "audio/x-spdif-compressed");
291
292 if (!trySPDIFonly)
293 av_probe_input_buffer(m_ioContext, &iformat, strFile.c_str(), NULL, 0, 0);
294
295 // Use the more low-level code in case we have been built against an old
296 // FFmpeg without the above av_probe_input_buffer(), or in case we only
297 // want to probe for spdif (DTS or IEC 61937) compressed audio
298 // specifically, or in case the file is a wav which may contain DTS or
299 // IEC 61937 (e.g. ac3-in-wav) and we want to check for those formats.
300 if (trySPDIFonly || (iformat && strcmp(iformat->name, "wav") == 0))
301 {
302 AVProbeData pd;
303 uint8_t probe_buffer[FFMPEG_FILE_BUFFER_SIZE + AVPROBE_PADDING_SIZE];
304
305 // init probe data
306 pd.buf = probe_buffer;
307 pd.filename = strFile.c_str();
308
309 // av_probe_input_buffer might have changed the buffer_size beyond our allocated amount
310 int buffer_size = std::min((int) FFMPEG_FILE_BUFFER_SIZE, m_ioContext->buffer_size);
311 // read data using avformat's buffers
312 pd.buf_size = avio_read(m_ioContext, pd.buf, m_ioContext->max_packet_size ? m_ioContext->max_packet_size : buffer_size);
313 if (pd.buf_size <= 0)
314 {
315 CLog::Log(LOGERROR, "%s - error reading from input stream, %s", __FUNCTION__, CURL::GetRedacted(strFile).c_str());
316 return false;
317 }
318 memset(pd.buf+pd.buf_size, 0, AVPROBE_PADDING_SIZE);
319
320 // restore position again
321 avio_seek(m_ioContext , 0, SEEK_SET);
322
323 // the advancedsetting is for allowing the user to force outputting the
324 // 44.1 kHz DTS wav file as PCM, so that an A/V receiver can decode
325 // it (this is temporary until we handle 44.1 kHz passthrough properly)
326 if (trySPDIFonly || (iformat && strcmp(iformat->name, "wav") == 0 && !g_advancedSettings.m_dvdplayerIgnoreDTSinWAV))
327 {
328 // check for spdif and dts
329 // This is used with wav files and audio CDs that may contain
330 // a DTS or AC3 track padded for S/PDIF playback. If neither of those
331 // is present, we assume it is PCM audio.
332 // AC3 is always wrapped in iec61937 (ffmpeg "spdif"), while DTS
333 // may be just padded.
334 AVInputFormat *iformat2;
335 iformat2 = av_find_input_format("spdif");
336
337 if (iformat2 && iformat2->read_probe(&pd) > AVPROBE_SCORE_MAX / 4)
338 {
339 iformat = iformat2;
340 }
341 else
342 {
343 // not spdif or no spdif demuxer, try dts
344 iformat2 = av_find_input_format("dts");
345
346 if (iformat2 && iformat2->read_probe(&pd) > AVPROBE_SCORE_MAX / 4)
347 {
348 iformat = iformat2;
349 }
350 else if (trySPDIFonly)
351 {
352 // not dts either, return false in case we were explicitely
353 // requested to only check for S/PDIF padded compressed audio
354 CLog::Log(LOGDEBUG, "%s - not spdif or dts file, fallbacking", __FUNCTION__);
355 return false;
356 }
357 }
358 }
359 }
360
361 if(!iformat)
362 {
363 std::string content = m_pInput->GetContent();
364
365 /* check if we can get a hint from content */
366 if( content.compare("audio/aacp") == 0 )
367 iformat = av_find_input_format("aac");
368 else if( content.compare("audio/aac") == 0 )
369 iformat = av_find_input_format("aac");
370 else if( content.compare("video/flv") == 0 )
371 iformat = av_find_input_format("flv");
372 else if( content.compare("video/x-flv") == 0 )
373 iformat = av_find_input_format("flv");
374 }
375
376 if (!iformat)
377 {
378 CLog::Log(LOGERROR, "%s - error probing input format, %s", __FUNCTION__, CURL::GetRedacted(strFile).c_str());
379 return false;
380 }
381 else
382 {
383 if (iformat->name)
384 CLog::Log(LOGDEBUG, "%s - probing detected format [%s]", __FUNCTION__, iformat->name);
385 else
386 CLog::Log(LOGDEBUG, "%s - probing detected unnamed format", __FUNCTION__);
387 }
388 }
389
390
391 m_pFormatContext->pb = m_ioContext;
392
393 AVDictionary *options = NULL;
394 if (iformat->name && (strcmp(iformat->name, "mp3") == 0 || strcmp(iformat->name, "mp2") == 0))
395 {
396 CLog::Log(LOGDEBUG, "%s - setting usetoc to 0 for accurate VBR MP3 seek", __FUNCTION__);
397 av_dict_set(&options, "usetoc", "0", 0);
398 }
399
400 if (StringUtils::StartsWith(content, "audio/l16"))
401 {
402 int channels = 2;
403 int samplerate = 44100;
404 GetL16Parameters(channels, samplerate);
405 av_dict_set_int(&options, "channels", channels, 0);
406 av_dict_set_int(&options, "sample_rate", samplerate, 0);
407 }
408
409 if (avformat_open_input(&m_pFormatContext, strFile.c_str(), iformat, &options) < 0)
410 {
411 CLog::Log(LOGERROR, "%s - Error, could not open file %s", __FUNCTION__, CURL::GetRedacted(strFile).c_str());
412 Dispose();
413 av_dict_free(&options);
414 return false;
415 }
416 av_dict_free(&options);
417 }
418
419 // Avoid detecting framerate if advancedsettings.xml says so
420 if (g_advancedSettings.m_videoFpsDetect == 0)
421 m_pFormatContext->fps_probe_size = 0;
422
423 // analyse very short to speed up mjpeg playback start
424 if (iformat && (strcmp(iformat->name, "mjpeg") == 0) && m_ioContext->seekable == 0)
425 av_opt_set_int(m_pFormatContext, "analyzeduration", 500000, 0);
426
427 bool skipCreateStreams = false;
428 bool isBluray = pInput->IsStreamType(DVDSTREAM_TYPE_BLURAY);
429 if (iformat && (strcmp(iformat->name, "mpegts") == 0) && !fileinfo && !isBluray)
430 {
431 av_opt_set_int(m_pFormatContext, "analyzeduration", 500000, 0);
432 m_checkvideo = true;
433 skipCreateStreams = true;
434 }
435 else if (!iformat || (strcmp(iformat->name, "mpegts") != 0))
436 {
437 m_streaminfo = true;
438 }
439
440 // we need to know if this is matroska or avi later
441 m_bMatroska = strncmp(m_pFormatContext->iformat->name, "matroska", 8) == 0; // for "matroska.webm"
442 m_bAVI = strcmp(m_pFormatContext->iformat->name, "avi") == 0;
443
444 if (m_streaminfo)
445 {
446 /* to speed up dvd switches, only analyse very short */
447 if(m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD))
448 av_opt_set_int(m_pFormatContext, "analyzeduration", 500000, 0);
449
450 CLog::Log(LOGDEBUG, "%s - avformat_find_stream_info starting", __FUNCTION__);
451 int iErr = avformat_find_stream_info(m_pFormatContext, NULL);
452 if (iErr < 0)
453 {
454 CLog::Log(LOGWARNING,"could not find codec parameters for %s", CURL::GetRedacted(strFile).c_str());
455 if (m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD)
456 || m_pInput->IsStreamType(DVDSTREAM_TYPE_BLURAY)
457 || (m_pFormatContext->nb_streams == 1 && m_pFormatContext->streams[0]->codec->codec_id == AV_CODEC_ID_AC3))
458 {
459 // special case, our codecs can still handle it.
460 }
461 else
462 {
463 Dispose();
464 return false;
465 }
466 }
467 CLog::Log(LOGDEBUG, "%s - av_find_stream_info finished", __FUNCTION__);
468
469 if (m_checkvideo)
470 {
471 // make sure we start video with an i-frame
472 ResetVideoStreams();
473 }
474 }
475 else
476 {
477 m_program = 0;
478 m_checkvideo = true;
479 skipCreateStreams = true;
480 }
481
482 // reset any timeout
483 m_timeout.SetInfinite();
484
485 // if format can be nonblocking, let's use that
486 m_pFormatContext->flags |= AVFMT_FLAG_NONBLOCK;
487
488 // print some extra information
489 av_dump_format(m_pFormatContext, 0, strFile.c_str(), 0);
490
491 UpdateCurrentPTS();
492
493 // in case of mpegts and we have not seen pat/pmt, defer creation of streams
494 if (!skipCreateStreams || m_pFormatContext->nb_programs > 0)
495 CreateStreams();
496
497 // allow IsProgramChange to return true
498 if (skipCreateStreams && GetNrOfStreams() == 0)
499 m_program = 0;
500
501 return true;
502}
503
504void CDVDDemuxFFmpeg::Dispose()
505{
506 m_pkt.result = -1;
507 av_free_packet(&m_pkt.pkt);
508
509 if (m_pFormatContext)
510 {
511 if (m_ioContext && m_pFormatContext->pb && m_pFormatContext->pb != m_ioContext)
512 {
513 CLog::Log(LOGWARNING, "CDVDDemuxFFmpeg::Dispose - demuxer changed our byte context behind our back, possible memleak");
514 m_ioContext = m_pFormatContext->pb;
515 }
516 avformat_close_input(&m_pFormatContext);
517 }
518
519 if(m_ioContext)
520 {
521 av_free(m_ioContext->buffer);
522 av_free(m_ioContext);
523 }
524
525 m_ioContext = NULL;
526 m_pFormatContext = NULL;
527 m_speed = DVD_PLAYSPEED_NORMAL;
528
529 DisposeStreams();
530
531 m_pInput = NULL;
532}
533
534void CDVDDemuxFFmpeg::Reset()
535{
536 CDVDInputStream* pInputStream = m_pInput;
537 Dispose();
538 Open(pInputStream, m_streaminfo);
539}
540
541void CDVDDemuxFFmpeg::Flush()
542{
543 // naughty usage of an internal ffmpeg function
544 if (m_pFormatContext)
545 av_read_frame_flush(m_pFormatContext);
546
547 m_currentPts = DVD_NOPTS_VALUE;
548
549 m_pkt.result = -1;
550 av_free_packet(&m_pkt.pkt);
551}
552
553void CDVDDemuxFFmpeg::Abort()
554{
555 m_timeout.SetExpired();
556}
557
558void CDVDDemuxFFmpeg::SetSpeed(int iSpeed)
559{
560 if(!m_pFormatContext)
561 return;
562
563 if(m_speed != DVD_PLAYSPEED_PAUSE && iSpeed == DVD_PLAYSPEED_PAUSE)
564 {
565 m_pInput->Pause(m_currentPts);
566 av_read_pause(m_pFormatContext);
567 }
568 else if(m_speed == DVD_PLAYSPEED_PAUSE && iSpeed != DVD_PLAYSPEED_PAUSE)
569 {
570 m_pInput->Pause(m_currentPts);
571 av_read_play(m_pFormatContext);
572 }
573 m_speed = iSpeed;
574
575 AVDiscard discard = AVDISCARD_NONE;
576 if(m_speed > 4*DVD_PLAYSPEED_NORMAL)
577 discard = AVDISCARD_NONKEY;
578 else if(m_speed > 2*DVD_PLAYSPEED_NORMAL)
579 discard = AVDISCARD_BIDIR;
580 else if(m_speed < DVD_PLAYSPEED_PAUSE)
581 discard = AVDISCARD_NONKEY;
582
583
584 for(unsigned int i = 0; i < m_pFormatContext->nb_streams; i++)
585 {
586 if(m_pFormatContext->streams[i])
587 {
588 if(m_pFormatContext->streams[i]->discard != AVDISCARD_ALL)
589 m_pFormatContext->streams[i]->discard = discard;
590 }
591 }
592}
593
594AVDictionary *CDVDDemuxFFmpeg::GetFFMpegOptionsFromURL(const CURL &url)
595{
596
597 AVDictionary *options = NULL;
598
599 if (url.IsProtocol("http") || url.IsProtocol("https"))
600 {
601 std::map<std::string, std::string> protocolOptions;
602 url.GetProtocolOptions(protocolOptions);
603 std::string headers;
604 bool hasUserAgent = false;
605 for(std::map<std::string, std::string>::const_iterator it = protocolOptions.begin(); it != protocolOptions.end(); ++it)
606 {
607 std::string name = it->first; StringUtils::ToLower(name);
608 const std::string &value = it->second;
609
610 if (name == "seekable")
611 av_dict_set(&options, "seekable", value.c_str(), 0);
612 else if (name == "user-agent")
613 {
614 av_dict_set(&options, "user-agent", value.c_str(), 0);
615 hasUserAgent = true;
616 }
617 else if (name != "auth" && name != "encoding")
618 // all other protocol options can be added as http header.
619 headers.append(it->first).append(": ").append(value).append("\r\n");
620 }
621 if (!hasUserAgent)
622 // set default xbmc user-agent.
623 av_dict_set(&options, "user-agent", g_advancedSettings.m_userAgent.c_str(), 0);
624
625 if (!headers.empty())
626 av_dict_set(&options, "headers", headers.c_str(), 0);
627
628 std::string cookies;
629 if (XFILE::CCurlFile::GetCookies(url, cookies))
630 av_dict_set(&options, "cookies", cookies.c_str(), 0);
631
632 }
633 return options;
634}
635
636double CDVDDemuxFFmpeg::ConvertTimestamp(int64_t pts, int den, int num)
637{
638 if (pts == (int64_t)AV_NOPTS_VALUE)
639 return DVD_NOPTS_VALUE;
640
641 // do calculations in floats as they can easily overflow otherwise
642 // we don't care for having a completly exact timestamp anyway
643 double timestamp = (double)pts * num / den;
644 double starttime = 0.0f;
645
646 // for dvd's we need the original time
647 if(CDVDInputStream::IMenus* menu = dynamic_cast<CDVDInputStream::IMenus*>(m_pInput))
648 starttime = menu->GetTimeStampCorrection() / DVD_TIME_BASE;
649 else if (m_pFormatContext->start_time != (int64_t)AV_NOPTS_VALUE)
650 starttime = (double)m_pFormatContext->start_time / AV_TIME_BASE;
651
652 if(timestamp > starttime)
653 timestamp -= starttime;
654 // allow for largest possible difference in pts and dts for a single packet
655 else if( timestamp + 0.5f > starttime )
656 timestamp = 0;
657
658 return timestamp*DVD_TIME_BASE;
659}
660
661DemuxPacket* CDVDDemuxFFmpeg::Read()
662{
663 DemuxPacket* pPacket = NULL;
664 // 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)
665 // would consider this the end of stream and stop.
666 bool bReturnEmpty = false;
667 { CSingleLock lock(m_critSection); // open lock scope
668 if (m_pFormatContext)
669 {
670 // assume we are not eof
671 if(m_pFormatContext->pb)
672 m_pFormatContext->pb->eof_reached = 0;
673
674 // check for saved packet after a program change
675 if (m_pkt.result < 0)
676 {
677 // keep track if ffmpeg doesn't always set these
678 m_pkt.pkt.size = 0;
679 m_pkt.pkt.data = NULL;
680
681 // timeout reads after 100ms
682 m_timeout.Set(20000);
683 m_pkt.result = av_read_frame(m_pFormatContext, &m_pkt.pkt);
684 m_timeout.SetInfinite();
685 }
686
687 if (m_pkt.result == AVERROR(EINTR) || m_pkt.result == AVERROR(EAGAIN))
688 {
689 // timeout, probably no real error, return empty packet
690 bReturnEmpty = true;
691 }
692 else if (m_pkt.result < 0)
693 {
694 Flush();
695 }
696 else if (IsProgramChange())
697 {
698 // update streams
699 CreateStreams(m_program);
700
701 pPacket = CDVDDemuxUtils::AllocateDemuxPacket(0);
702 pPacket->iStreamId = DMX_SPECIALID_STREAMCHANGE;
703
704 return pPacket;
705 }
706 // check size and stream index for being in a valid range
707 else if (m_pkt.pkt.size < 0 ||
708 m_pkt.pkt.stream_index < 0 ||
709 m_pkt.pkt.stream_index >= (int)m_pFormatContext->nb_streams)
710 {
711 // XXX, in some cases ffmpeg returns a negative packet size
712 if(m_pFormatContext->pb && !m_pFormatContext->pb->eof_reached)
713 {
714 CLog::Log(LOGERROR, "CDVDDemuxFFmpeg::Read() no valid packet");
715 bReturnEmpty = true;
716 Flush();
717 }
718 else
719 CLog::Log(LOGERROR, "CDVDDemuxFFmpeg::Read() returned invalid packet and eof reached");
720
721 m_pkt.result = -1;
722 av_free_packet(&m_pkt.pkt);
723 }
724 else
725 {
726 ParsePacket(&m_pkt.pkt);
727
728 AVStream *stream = m_pFormatContext->streams[m_pkt.pkt.stream_index];
729
730 if (IsVideoReady())
731 {
732 if (m_program != UINT_MAX)
733 {
734 /* check so packet belongs to selected program */
735 for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++)
736 {
737 if(m_pkt.pkt.stream_index == (int)m_pFormatContext->programs[m_program]->stream_index[i])
738 {
739 pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size);
740 break;
741 }
742 }
743
744 if (!pPacket)
745 bReturnEmpty = true;
746 }
747 else
748 pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size);
749 }
750 else
751 bReturnEmpty = true;
752
753 if (pPacket)
754 {
755 // lavf sometimes bugs out and gives 0 dts/pts instead of no dts/pts
756 // since this could only happens on initial frame under normal
757 // circomstances, let's assume it is wrong all the time
758 if(m_pkt.pkt.dts == 0)
759 m_pkt.pkt.dts = AV_NOPTS_VALUE;
760 if(m_pkt.pkt.pts == 0)
761 m_pkt.pkt.pts = AV_NOPTS_VALUE;
762
763 if(m_bMatroska && stream->codec && stream->codec->codec_type == AVMEDIA_TYPE_VIDEO)
764 { // matroska can store different timestamps
765 // for different formats, for native stored
766 // stuff it is pts, but for ms compatibility
767 // tracks, it is really dts. sadly ffmpeg
768 // sets these two timestamps equal all the
769 // time, so we select it here instead
770 if(stream->codec->codec_tag == 0)
771 m_pkt.pkt.dts = AV_NOPTS_VALUE;
772 else
773 m_pkt.pkt.pts = AV_NOPTS_VALUE;
774 }
775
776 // we need to get duration slightly different for matroska embedded text subtitels
777 if(m_bMatroska && stream->codec && stream->codec->codec_id == AV_CODEC_ID_TEXT && m_pkt.pkt.convergence_duration != 0)
778 m_pkt.pkt.duration = m_pkt.pkt.convergence_duration;
779
780 if(m_bAVI && stream->codec && stream->codec->codec_type == AVMEDIA_TYPE_VIDEO)
781 {
782 // AVI's always have borked pts, specially if m_pFormatContext->flags includes
783 // AVFMT_FLAG_GENPTS so always use dts
784 m_pkt.pkt.pts = AV_NOPTS_VALUE;
785 }
786
787 // copy contents into our own packet
788 pPacket->iSize = m_pkt.pkt.size;
789
790 // maybe we can avoid a memcpy here by detecting where pkt.destruct is pointing too?
791 if (m_pkt.pkt.data)
792 memcpy(pPacket->pData, m_pkt.pkt.data, pPacket->iSize);
793
794 pPacket->pts = ConvertTimestamp(m_pkt.pkt.pts, stream->time_base.den, stream->time_base.num);
795 pPacket->dts = ConvertTimestamp(m_pkt.pkt.dts, stream->time_base.den, stream->time_base.num);
796 pPacket->duration = DVD_SEC_TO_TIME((double)m_pkt.pkt.duration * stream->time_base.num / stream->time_base.den);
797
798 // used to guess streamlength
799 if (pPacket->dts != DVD_NOPTS_VALUE && (pPacket->dts > m_currentPts || m_currentPts == DVD_NOPTS_VALUE))
800 m_currentPts = pPacket->dts;
801
802
803 // check if stream has passed full duration, needed for live streams
804 bool bAllowDurationExt = (stream->codec && (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO || stream->codec->codec_type == AVMEDIA_TYPE_AUDIO));
805 if(bAllowDurationExt && m_pkt.pkt.dts != (int64_t)AV_NOPTS_VALUE)
806 {
807 int64_t duration;
808 duration = m_pkt.pkt.dts;
809 if(stream->start_time != (int64_t)AV_NOPTS_VALUE)
810 duration -= stream->start_time;
811
812 if(duration > stream->duration)
813 {
814 stream->duration = duration;
815 duration = av_rescale_rnd(stream->duration, (int64_t)stream->time_base.num * AV_TIME_BASE, stream->time_base.den, AV_ROUND_NEAR_INF);
816 if ((m_pFormatContext->duration == (int64_t)AV_NOPTS_VALUE)
817 || (m_pFormatContext->duration != (int64_t)AV_NOPTS_VALUE && duration > m_pFormatContext->duration))
818 m_pFormatContext->duration = duration;
819 }
820 }
821
822 // store internal id until we know the continuous id presented to player
823 // the stream might not have been created yet
824 pPacket->iStreamId = m_pkt.pkt.stream_index;
825 }
826 m_pkt.result = -1;
827 av_free_packet(&m_pkt.pkt);
828 }
829 }
830 } // end of lock scope
831 if (bReturnEmpty && !pPacket)
832 pPacket = CDVDDemuxUtils::AllocateDemuxPacket(0);
833
834 if (!pPacket) return NULL;
835
836 // check streams, can we make this a bit more simple?
837 if (pPacket && pPacket->iStreamId >= 0)
838 {
839 CDemuxStream *stream = GetStreamInternal(pPacket->iStreamId);
840 if (!stream ||
841 stream->pPrivate != m_pFormatContext->streams[pPacket->iStreamId] ||
842 stream->codec != m_pFormatContext->streams[pPacket->iStreamId]->codec->codec_id)
843 {
844 // content has changed, or stream did not yet exist
845 stream = AddStream(pPacket->iStreamId);
846 }
847 // we already check for a valid m_streams[pPacket->iStreamId] above
848 else if (stream->type == STREAM_AUDIO)
849 {
850 if (((CDemuxStreamAudio*)stream)->iChannels != m_pFormatContext->streams[pPacket->iStreamId]->codec->channels ||
851 ((CDemuxStreamAudio*)stream)->iSampleRate != m_pFormatContext->streams[pPacket->iStreamId]->codec->sample_rate)
852 {
853 // content has changed
854 stream = AddStream(pPacket->iStreamId);
855 }
856 }
857 else if (stream->type == STREAM_VIDEO)
858 {
859 if (((CDemuxStreamVideo*)stream)->iWidth != m_pFormatContext->streams[pPacket->iStreamId]->codec->width ||
860 ((CDemuxStreamVideo*)stream)->iHeight != m_pFormatContext->streams[pPacket->iStreamId]->codec->height)
861 {
862 // content has changed
863 stream = AddStream(pPacket->iStreamId);
864 }
865 }
866 if (!stream)
867 {
868 CLog::Log(LOGERROR, "CDVDDemuxFFmpeg::AddStream - internal error, stream is null");
869 CDVDDemuxUtils::FreeDemuxPacket(pPacket);
870 return NULL;
871 }
872 // set continuous stream id for player
873 pPacket->iStreamId = stream->iId;
874 }
875 return pPacket;
876}
877
878bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts)
879{
880 if (!m_pInput)
881 return false;
882
883 if(time < 0)
884 time = 0;
885
886 m_pkt.result = -1;
887 av_free_packet(&m_pkt.pkt);
888
889 CDVDInputStream::ISeekTime* ist = dynamic_cast<CDVDInputStream::ISeekTime*>(m_pInput);
890 if (ist)
891 {
892 if (!ist->SeekTime(time))
893 return false;
894
895 if(startpts)
896 *startpts = DVD_NOPTS_VALUE;
897
898 Flush();
899
900 // also empty the internal ffmpeg buffer
901 m_ioContext->buf_ptr = m_ioContext->buf_end;
902
903 return true;
904 }
905
906 if(!m_pInput->Seek(0, SEEK_POSSIBLE)
907 && !m_pInput->IsStreamType(DVDSTREAM_TYPE_FFMPEG))
908 {
909 CLog::Log(LOGDEBUG, "%s - input stream reports it is not seekable", __FUNCTION__);
910 return false;
911 }
912
913 int64_t seek_pts = (int64_t)time * (AV_TIME_BASE / 1000);
914 bool ismp3 = m_pFormatContext->iformat && (strcmp(m_pFormatContext->iformat->name, "mp3") == 0);
915 if (m_pFormatContext->start_time != (int64_t)AV_NOPTS_VALUE && !ismp3)
916 seek_pts += m_pFormatContext->start_time;
917
918 int ret;
919 {
920 CSingleLock lock(m_critSection);
921 ret = av_seek_frame(m_pFormatContext, -1, seek_pts, backwords ? AVSEEK_FLAG_BACKWARD : 0);
922
923 // demuxer will return failure, if you seek behind eof
924 if (ret < 0 && m_pFormatContext->duration && seek_pts >= (m_pFormatContext->duration + m_pFormatContext->start_time))
925 ret = 0;
926 else if (ret < 0 && m_pInput->IsEOF())
927 ret = 0;
928
929 if(ret >= 0)
930 UpdateCurrentPTS();
931 }
932
933 if(m_currentPts == DVD_NOPTS_VALUE)
934 CLog::Log(LOGDEBUG, "%s - unknown position after seek", __FUNCTION__);
935 else
936 CLog::Log(LOGDEBUG, "%s - seek ended up on time %d", __FUNCTION__, (int)(m_currentPts / DVD_TIME_BASE * 1000));
937
938 // in this case the start time is requested time
939 if(startpts)
940 *startpts = DVD_MSEC_TO_TIME(time);
941
942 return (ret >= 0);
943}
944
945bool CDVDDemuxFFmpeg::SeekByte(int64_t pos)
946{
947 CSingleLock lock(m_critSection);
948 int ret = av_seek_frame(m_pFormatContext, -1, pos, AVSEEK_FLAG_BYTE);
949
950 if(ret >= 0)
951 UpdateCurrentPTS();
952
953 m_pkt.result = -1;
954 av_free_packet(&m_pkt.pkt);
955
956 return (ret >= 0);
957}
958
959void CDVDDemuxFFmpeg::UpdateCurrentPTS()
960{
961 m_currentPts = DVD_NOPTS_VALUE;
962
963 int idx = av_find_default_stream_index(m_pFormatContext);
964 if (idx >= 0)
965 {
966 AVStream *stream = m_pFormatContext->streams[idx];
967 if(stream && stream->cur_dts != (int64_t)AV_NOPTS_VALUE)
968 {
969 double ts = ConvertTimestamp(stream->cur_dts, stream->time_base.den, stream->time_base.num);
970 if(m_currentPts == DVD_NOPTS_VALUE || m_currentPts > ts )
971 m_currentPts = ts;
972 }
973 }
974}
975
976int CDVDDemuxFFmpeg::GetStreamLength()
977{
978 if (!m_pFormatContext)
979 return 0;
980
981 if (m_pFormatContext->duration < 0)
982 return 0;
983
984 return (int)(m_pFormatContext->duration / (AV_TIME_BASE / 1000));
985}
986
987/**
988 * @brief Finds stream based on demuxer index
989 */
990CDemuxStream* CDVDDemuxFFmpeg::GetStream(int iStreamId)
991{
992 if(iStreamId >= 0 && (size_t)iStreamId < m_stream_index.size())
993 return m_stream_index[iStreamId]->second;
994 else
995 return NULL;
996}
997
998/**
999 * @brief Finds stream based on ffmpeg index
1000 */
1001CDemuxStream* CDVDDemuxFFmpeg::GetStreamInternal(int iId)
1002{
1003 std::map<int, CDemuxStream*>::iterator it = m_streams.find(iId);
1004 if (it == m_streams.end())
1005 return NULL;
1006 else
1007 return it->second;
1008}
1009
1010int CDVDDemuxFFmpeg::GetNrOfStreams()
1011{
1012 return m_stream_index.size();
1013}
1014
1015static double SelectAspect(AVStream* st, bool* forced)
1016{
1017 *forced = false;
1018 /* if stream aspect is 1:1 or 0:0 use codec aspect */
1019 if((st->sample_aspect_ratio.den == 1 || st->sample_aspect_ratio.den == 0)
1020 && (st->sample_aspect_ratio.num == 1 || st->sample_aspect_ratio.num == 0)
1021 && st->codec->sample_aspect_ratio.num != 0)
1022 return av_q2d(st->codec->sample_aspect_ratio);
1023
1024 *forced = true;
1025 if(st->sample_aspect_ratio.num != 0)
1026 return av_q2d(st->sample_aspect_ratio);
1027
1028 return 0.0;
1029}
1030
1031void CDVDDemuxFFmpeg::CreateStreams(unsigned int program)
1032{
1033 DisposeStreams();
1034
1035 // add the ffmpeg streams to our own stream map
1036 if (m_pFormatContext->nb_programs)
1037 {
1038 // check if desired program is available
1039 if (program < m_pFormatContext->nb_programs && m_pFormatContext->programs[program]->nb_stream_indexes > 0)
1040 {
1041 m_program = program;
1042 }
1043 else
1044 m_program = UINT_MAX;
1045
1046 // look for first non empty stream and discard nonselected programs
1047 for (unsigned int i = 0; i < m_pFormatContext->nb_programs; i++)
1048 {
1049 if(m_program == UINT_MAX && m_pFormatContext->programs[i]->nb_stream_indexes > 0)
1050 {
1051 m_program = i;
1052 }
1053
1054 if(i != m_program)
1055 m_pFormatContext->programs[i]->discard = AVDISCARD_ALL;
1056 }
1057 if(m_program != UINT_MAX)
1058 {
1059 // add streams from selected program
1060 for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++)
1061 AddStream(m_pFormatContext->programs[m_program]->stream_index[i]);
1062 }
1063 }
1064 else
1065 m_program = UINT_MAX;
1066
1067 // if there were no programs or they were all empty, add all streams
1068 if (m_program == UINT_MAX)
1069 {
1070 for (unsigned int i = 0; i < m_pFormatContext->nb_streams; i++)
1071 AddStream(i);
1072 }
1073}
1074
1075void CDVDDemuxFFmpeg::DisposeStreams()
1076{
1077 std::map<int, CDemuxStream*>::iterator it;
1078 for(it = m_streams.begin(); it != m_streams.end(); ++it)
1079 delete it->second;
1080 m_streams.clear();
1081 m_stream_index.clear();
1082}
1083
1084CDemuxStream* CDVDDemuxFFmpeg::AddStream(int iId)
1085{
1086 AVStream* pStream = m_pFormatContext->streams[iId];
1087 if (pStream)
1088 {
1089 CDemuxStream* stream = NULL;
1090
1091 switch (pStream->codec->codec_type)
1092 {
1093 case AVMEDIA_TYPE_AUDIO:
1094 {
1095 CDemuxStreamAudioFFmpeg* st = new CDemuxStreamAudioFFmpeg(this, pStream);
1096 stream = st;
1097 st->iChannels = pStream->codec->channels;
1098 st->iSampleRate = pStream->codec->sample_rate;
1099 st->iBlockAlign = pStream->codec->block_align;
1100 st->iBitRate = pStream->codec->bit_rate;
1101 st->iBitsPerSample = pStream->codec->bits_per_raw_sample;
1102 if (st->iBitsPerSample == 0)
1103 st->iBitsPerSample = pStream->codec->bits_per_coded_sample;
1104
1105 if(av_dict_get(pStream->metadata, "title", NULL, 0))
1106 st->m_description = av_dict_get(pStream->metadata, "title", NULL, 0)->value;
1107
1108 break;
1109 }
1110 case AVMEDIA_TYPE_VIDEO:
1111 {
1112 CDemuxStreamVideoFFmpeg* st = new CDemuxStreamVideoFFmpeg(this, pStream);
1113 stream = st;
1114 if(strcmp(m_pFormatContext->iformat->name, "flv") == 0)
1115 st->bVFR = true;
1116 else
1117 st->bVFR = false;
1118
1119 // never trust pts in avi files with h264.
1120 if (m_bAVI && pStream->codec->codec_id == AV_CODEC_ID_H264)
1121 st->bPTSInvalid = true;
1122
1123#if defined(AVFORMAT_HAS_STREAM_GET_R_FRAME_RATE)
1124 AVRational r_frame_rate = av_stream_get_r_frame_rate(pStream);
1125#else
1126 AVRational r_frame_rate = pStream->r_frame_rate;
1127#endif
1128
1129 //average fps is more accurate for mkv files
1130 if (m_bMatroska && pStream->avg_frame_rate.den && pStream->avg_frame_rate.num)
1131 {
1132 st->iFpsRate = pStream->avg_frame_rate.num;
1133 st->iFpsScale = pStream->avg_frame_rate.den;
1134 }
1135 else if(r_frame_rate.den && r_frame_rate.num)
1136 {
1137 st->iFpsRate = r_frame_rate.num;
1138 st->iFpsScale = r_frame_rate.den;
1139 }
1140 else
1141 {
1142 st->iFpsRate = 0;
1143 st->iFpsScale = 0;
1144 }
1145
1146 // added for aml hw decoder, mkv frame-rate can be wrong.
1147 if (r_frame_rate.den && r_frame_rate.num)
1148 {
1149 st->irFpsRate = r_frame_rate.num;
1150 st->irFpsScale = r_frame_rate.den;
1151 }
1152 else
1153 {
1154 st->irFpsRate = 0;
1155 st->irFpsScale = 0;
1156 }
1157
1158 if (pStream->codec_info_nb_frames > 0
1159 && pStream->codec_info_nb_frames <= 2
1160 && m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD))
1161 {
1162 CLog::Log(LOGDEBUG, "%s - fps may be unreliable since ffmpeg decoded only %d frame(s)", __FUNCTION__, pStream->codec_info_nb_frames);
1163 st->iFpsRate = 0;
1164 st->iFpsScale = 0;
1165 }
1166
1167 st->iWidth = pStream->codec->width;
1168 st->iHeight = pStream->codec->height;
1169 st->fAspect = SelectAspect(pStream, &st->bForcedAspect) * pStream->codec->width / pStream->codec->height;
1170 st->iOrientation = 0;
1171 st->iBitsPerPixel = pStream->codec->bits_per_coded_sample;
1172
1173 AVDictionaryEntry *rtag = av_dict_get(pStream->metadata, "rotate", NULL, 0);
1174 if (rtag)
1175 st->iOrientation = atoi(rtag->value);
1176
1177 // detect stereoscopic mode
1178 std::string stereoMode = GetStereoModeFromMetadata(pStream->metadata);
1179 // check for metadata in file if detection in stream failed
1180 if (stereoMode.empty())
1181 stereoMode = GetStereoModeFromMetadata(m_pFormatContext->metadata);
1182 if (!stereoMode.empty())
1183 st->stereo_mode = stereoMode;
1184
1185
1186 if ( m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD) )
1187 {
1188 if (pStream->codec->codec_id == AV_CODEC_ID_PROBE)
1189 {
1190 // fix MPEG-1/MPEG-2 video stream probe returning AV_CODEC_ID_PROBE for still frames.
1191 // ffmpeg issue 1871, regression from ffmpeg r22831.
1192 if ((pStream->id & 0xF0) == 0xE0)
1193 {
1194 pStream->codec->codec_id = AV_CODEC_ID_MPEG2VIDEO;
1195 pStream->codec->codec_tag = MKTAG('M','P','2','V');
1196 CLog::Log(LOGERROR, "%s - AV_CODEC_ID_PROBE detected, forcing AV_CODEC_ID_MPEG2VIDEO", __FUNCTION__);
1197 }
1198 }
1199 }
1200 break;
1201 }
1202 case AVMEDIA_TYPE_DATA:
1203 {
1204 stream = new CDemuxStream();
1205 stream->type = STREAM_DATA;
1206 break;
1207 }
1208 case AVMEDIA_TYPE_SUBTITLE:
1209 {
1210 if (pStream->codec->codec_id == AV_CODEC_ID_DVB_TELETEXT && CSettings::Get().GetBool("videoplayer.teletextenabled"))
1211 {
1212 CDemuxStreamTeletext* st = new CDemuxStreamTeletext();
1213 stream = st;
1214 stream->type = STREAM_TELETEXT;
1215 break;
1216 }
1217 else
1218 {
1219 CDemuxStreamSubtitleFFmpeg* st = new CDemuxStreamSubtitleFFmpeg(this, pStream);
1220 stream = st;
1221
1222 if(av_dict_get(pStream->metadata, "title", NULL, 0))
1223 st->m_description = av_dict_get(pStream->metadata, "title", NULL, 0)->value;
1224
1225 break;
1226 }
1227 }
1228 case AVMEDIA_TYPE_ATTACHMENT:
1229 { //mkv attachments. Only bothering with fonts for now.
1230 if(pStream->codec->codec_id == AV_CODEC_ID_TTF
1231 || pStream->codec->codec_id == AV_CODEC_ID_OTF
1232 )
1233 {
1234 std::string fileName = "special://temp/fonts/";
1235 XFILE::CDirectory::Create(fileName);
1236 AVDictionaryEntry *nameTag = av_dict_get(pStream->metadata, "filename", NULL, 0);
1237 if (!nameTag)
1238 {
1239 CLog::Log(LOGERROR, "%s: TTF attachment has no name", __FUNCTION__);
1240 }
1241 else
1242 {
1243 fileName += nameTag->value;
1244 XFILE::CFile file;
1245 if(pStream->codec->extradata && file.OpenForWrite(fileName))
1246 {
1247 if (file.Write(pStream->codec->extradata, pStream->codec->extradata_size) != pStream->codec->extradata_size)
1248 {
1249 file.Close();
1250 XFILE::CFile::Delete(fileName);
1251 CLog::Log(LOGDEBUG, "%s: Error saving font file \"%s\"", __FUNCTION__, fileName.c_str());
1252 }
1253 }
1254 }
1255 }
1256 stream = new CDemuxStream();
1257 stream->type = STREAM_NONE;
1258 break;
1259 }
1260 default:
1261 {
1262 stream = new CDemuxStream();
1263 stream->type = STREAM_NONE;
1264 break;
1265 }
1266 }
1267
1268 // set ffmpeg type
1269 stream->orig_type = pStream->codec->codec_type;
1270
1271 // generic stuff
1272 if (pStream->duration != (int64_t)AV_NOPTS_VALUE)
1273 stream->iDuration = (int)((pStream->duration / AV_TIME_BASE) & 0xFFFFFFFF);
1274
1275 stream->codec = pStream->codec->codec_id;
1276 stream->codec_fourcc = pStream->codec->codec_tag;
1277 stream->profile = pStream->codec->profile;
1278 stream->level = pStream->codec->level;
1279
1280 stream->source = STREAM_SOURCE_DEMUX;
1281 stream->pPrivate = pStream;
1282 stream->flags = (CDemuxStream::EFlags)pStream->disposition;
1283
1284 AVDictionaryEntry *langTag = av_dict_get(pStream->metadata, "language", NULL, 0);
1285 if (langTag)
1286 strncpy(stream->language, langTag->value, 3);
1287
1288 if( pStream->codec->extradata && pStream->codec->extradata_size > 0 )
1289 {
1290 stream->ExtraSize = pStream->codec->extradata_size;
1291 stream->ExtraData = new uint8_t[pStream->codec->extradata_size];
1292 memcpy(stream->ExtraData, pStream->codec->extradata, pStream->codec->extradata_size);
1293 }
1294
1295#ifdef HAVE_LIBBLURAY
1296 if( m_pInput->IsStreamType(DVDSTREAM_TYPE_BLURAY) )
1297 static_cast<CDVDInputStreamBluray*>(m_pInput)->GetStreamInfo(pStream->id, stream->language);
1298#endif
1299 if( m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD) )
1300 {
1301 // this stuff is really only valid for dvd's.
1302 // this is so that the physicalid matches the
1303 // id's reported from libdvdnav
1304 switch(stream->codec)
1305 {
1306 case AV_CODEC_ID_AC3:
1307 stream->iPhysicalId = pStream->id - 128;
1308 break;
1309 case AV_CODEC_ID_DTS:
1310 stream->iPhysicalId = pStream->id - 136;
1311 break;
1312 case AV_CODEC_ID_MP2:
1313 stream->iPhysicalId = pStream->id - 448;
1314 break;
1315 case AV_CODEC_ID_PCM_S16BE:
1316 stream->iPhysicalId = pStream->id - 160;
1317 break;
1318 case AV_CODEC_ID_DVD_SUBTITLE:
1319 stream->iPhysicalId = pStream->id - 0x20;
1320 break;
1321 default:
1322 stream->iPhysicalId = pStream->id & 0x1f;
1323 break;
1324 }
1325 }
1326 else
1327 stream->iPhysicalId = pStream->id;
1328
1329 AddStream(iId, stream);
1330 return stream;
1331 }
1332 else
1333 return NULL;
1334}
1335
1336/**
1337 * @brief Adds or updates a demux stream based in ffmpeg id
1338 */
1339void CDVDDemuxFFmpeg::AddStream(int iId, CDemuxStream* stream)
1340{
1341 std::pair<std::map<int, CDemuxStream*>::iterator, bool> res;
1342
1343 res = m_streams.insert(std::make_pair(iId, stream));
1344 if(res.second)
1345 {
1346 /* was new stream */
1347 stream->iId = m_stream_index.size();
1348 m_stream_index.push_back(res.first);
1349 }
1350 else
1351 {
1352 /* replace old stream, keeping old index */
1353 stream->iId = res.first->second->iId;
1354
1355 delete res.first->second;
1356 res.first->second = stream;
1357 }
1358 if(g_advancedSettings.m_logLevel > LOG_LEVEL_NORMAL)
1359 CLog::Log(LOGDEBUG, "CDVDDemuxFFmpeg::AddStream(%d, ...) -> %d", iId, stream->iId);
1360}
1361
1362
1363std::string CDVDDemuxFFmpeg::GetFileName()
1364{
1365 if(m_pInput)
1366 return m_pInput->GetFileName();
1367 else
1368 return "";
1369}
1370
1371int CDVDDemuxFFmpeg::GetChapterCount()
1372{
1373 CDVDInputStream::IChapter* ich = dynamic_cast<CDVDInputStream::IChapter*>(m_pInput);
1374 if(ich)
1375 return ich->GetChapterCount();
1376
1377 if(m_pFormatContext == NULL)
1378 return 0;
1379
1380 return m_pFormatContext->nb_chapters;
1381}
1382
1383int CDVDDemuxFFmpeg::GetChapter()
1384{
1385 CDVDInputStream::IChapter* ich = dynamic_cast<CDVDInputStream::IChapter*>(m_pInput);
1386 if(ich)
1387 return ich->GetChapter();
1388
1389 if(m_pFormatContext == NULL
1390 || m_currentPts == DVD_NOPTS_VALUE)
1391 return 0;
1392
1393 for(unsigned i = 0; i < m_pFormatContext->nb_chapters; i++)
1394 {
1395 AVChapter *chapter = m_pFormatContext->chapters[i];
1396 if(m_currentPts >= ConvertTimestamp(chapter->start, chapter->time_base.den, chapter->time_base.num)
1397 && m_currentPts < ConvertTimestamp(chapter->end, chapter->time_base.den, chapter->time_base.num))
1398 return i + 1;
1399 }
1400
1401 return 0;
1402}
1403
1404void CDVDDemuxFFmpeg::GetChapterName(std::string& strChapterName, int chapterIdx)
1405{
1406 if (chapterIdx <= 0 || chapterIdx > GetChapterCount())
1407 chapterIdx = GetChapter();
1408 CDVDInputStream::IChapter* ich = dynamic_cast<CDVDInputStream::IChapter*>(m_pInput);
1409 if(ich)
1410 ich->GetChapterName(strChapterName, chapterIdx);
1411 else
1412 {
1413 if(chapterIdx <= 0)
1414 return;
1415
1416 AVDictionaryEntry *titleTag = av_dict_get(m_pFormatContext->chapters[chapterIdx-1]->metadata,
1417 "title", NULL, 0);
1418 if (titleTag)
1419 strChapterName = titleTag->value;
1420 }
1421}
1422
1423int64_t CDVDDemuxFFmpeg::GetChapterPos(int chapterIdx)
1424{
1425 if (chapterIdx <= 0 || chapterIdx > GetChapterCount())
1426 chapterIdx = GetChapter();
1427 if(chapterIdx <= 0)
1428 return 0;
1429
1430 CDVDInputStream::IChapter* ich = dynamic_cast<CDVDInputStream::IChapter*>(m_pInput);
1431 if(ich)
1432 return ich->GetChapterPos(chapterIdx);
1433
1434 return m_pFormatContext->chapters[chapterIdx-1]->start*av_q2d(m_pFormatContext->chapters[chapterIdx-1]->time_base);
1435}
1436
1437bool CDVDDemuxFFmpeg::SeekChapter(int chapter, double* startpts)
1438{
1439 if(chapter < 1)
1440 chapter = 1;
1441
1442 CDVDInputStream::IChapter* ich = dynamic_cast<CDVDInputStream::IChapter*>(m_pInput);
1443 if(ich)
1444 {
1445 CLog::Log(LOGDEBUG, "%s - chapter seeking using input stream", __FUNCTION__);
1446 if(!ich->SeekChapter(chapter))
1447 return false;
1448
1449 if(startpts)
1450 {
1451 *startpts = DVD_SEC_TO_TIME(ich->GetChapterPos(chapter));
1452 }
1453
1454 Flush();
1455 return true;
1456 }
1457
1458 if(m_pFormatContext == NULL)
1459 return false;
1460
1461 if(chapter < 1 || chapter > (int)m_pFormatContext->nb_chapters)
1462 return false;
1463
1464 AVChapter *ch = m_pFormatContext->chapters[chapter-1];
1465 double dts = ConvertTimestamp(ch->start, ch->time_base.den, ch->time_base.num);
1466 return SeekTime(DVD_TIME_TO_MSEC(dts), true, startpts);
1467}
1468
1469void CDVDDemuxFFmpeg::GetStreamCodecName(int iStreamId, std::string &strName)
1470{
1471 CDemuxStream *stream = GetStream(iStreamId);
1472 if (stream)
1473 {
1474 unsigned int in = stream->codec_fourcc;
1475 // FourCC codes are only valid on video streams, audio codecs in AVI/WAV
1476 // are 2 bytes and audio codecs in transport streams have subtle variation
1477 // e.g AC-3 instead of ac3
1478 if (stream->type == STREAM_VIDEO && in != 0)
1479 {
1480 char fourcc[5];
1481#if defined(__powerpc__)
1482 fourcc[0] = in & 0xff;
1483 fourcc[1] = (in >> 8) & 0xff;
1484 fourcc[2] = (in >> 16) & 0xff;
1485 fourcc[3] = (in >> 24) & 0xff;
1486#else
1487 memcpy(fourcc, &in, 4);
1488#endif
1489 fourcc[4] = 0;
1490 // fourccs have to be 4 characters
1491 if (strlen(fourcc) == 4)
1492 {
1493 strName = fourcc;
1494 StringUtils::ToLower(strName);
1495 return;
1496 }
1497 }
1498
1499#ifdef FF_PROFILE_DTS_HD_MA
1500 /* use profile to determine the DTS type */
1501 if (stream->codec == AV_CODEC_ID_DTS)
1502 {
1503 if (stream->profile == FF_PROFILE_DTS_HD_MA)
1504 strName = "dtshd_ma";
1505 else if (stream->profile == FF_PROFILE_DTS_HD_HRA)
1506 strName = "dtshd_hra";
1507 else
1508 strName = "dca";
1509 return;
1510 }
1511#endif
1512
1513 AVCodec *codec = avcodec_find_decoder(stream->codec);
1514 if (codec)
1515 strName = codec->name;
1516 }
1517}
1518
1519bool CDVDDemuxFFmpeg::IsProgramChange()
1520{
1521 if (m_program == UINT_MAX)
1522 return false;
1523
1524 if (m_program == 0 && !m_pFormatContext->nb_programs)
1525 return false;
1526
1527 if(m_pFormatContext->programs[m_program]->nb_stream_indexes != m_streams.size())
1528 return true;
1529
1530 if (m_program >= m_pFormatContext->nb_programs)
1531 return true;
1532
1533 for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++)
1534 {
1535 int idx = m_pFormatContext->programs[m_program]->stream_index[i];
1536 CDemuxStream *stream = GetStreamInternal(idx);
1537 if(!stream)
1538 return true;
1539 if(m_pFormatContext->streams[idx]->codec->codec_type != stream->orig_type)
1540 return true;
1541 }
1542 return false;
1543}
1544
1545std::string CDVDDemuxFFmpeg::GetStereoModeFromMetadata(AVDictionary *pMetadata)
1546{
1547 std::string stereoMode;
1548 AVDictionaryEntry *tag = NULL;
1549
1550 // matroska
1551 tag = av_dict_get(pMetadata, "stereo_mode", NULL, 0);
1552 if (tag && tag->value)
1553 stereoMode = tag->value;
1554
1555 // asf / wmv
1556 if (stereoMode.empty())
1557 {
1558 tag = av_dict_get(pMetadata, "Stereoscopic", NULL, 0);
1559 if (tag && tag->value)
1560 {
1561 tag = av_dict_get(pMetadata, "StereoscopicLayout", NULL, 0);
1562 if (tag && tag->value)
1563 stereoMode = ConvertCodecToInternalStereoMode(tag->value, WmvToInternalStereoModeMap);
1564 }
1565 }
1566
1567 return stereoMode;
1568}
1569
1570std::string CDVDDemuxFFmpeg::ConvertCodecToInternalStereoMode(const std::string &mode, const StereoModeConversionMap *conversionMap)
1571{
1572 size_t i = 0;
1573 while (conversionMap[i].name)
1574 {
1575 if (mode == conversionMap[i].name)
1576 return conversionMap[i].mode;
1577 i++;
1578 }
1579 return "";
1580}
1581
1582void CDVDDemuxFFmpeg::ParsePacket(AVPacket *pkt)
1583{
1584 AVStream *st = m_pFormatContext->streams[pkt->stream_index];
1585 CDemuxStream *stream = GetStreamInternal(pkt->stream_index);
1586
1587 // if the stream is new, tell ffmpeg to parse the stream
1588 if (!stream && !st->parser)
1589 {
1590 st->need_parsing = AVSTREAM_PARSE_FULL;
1591 }
1592
1593 // split extradata
1594 if(st->parser && st->parser->parser->split && !st->codec->extradata)
1595 {
1596 int i = st->parser->parser->split(st->codec, pkt->data, pkt->size);
1597 if (i > 0 && i < FF_MAX_EXTRADATA_SIZE)
1598 {
1599 // Found extradata, fill it in. This will cause
1600 // a new stream to be created and used.
1601 st->codec->extradata_size = i;
1602 st->codec->extradata = (uint8_t*)av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
1603 if (st->codec->extradata)
1604 {
1605 CLog::Log(LOGDEBUG, "CDVDDemuxFFmpeg::Read() fetching extradata, extradata_size(%d)", st->codec->extradata_size);
1606 memcpy(st->codec->extradata, pkt->data, st->codec->extradata_size);
1607 memset(st->codec->extradata + i, 0, FF_INPUT_BUFFER_PADDING_SIZE);
1608 }
1609 else
1610 {
1611 st->codec->extradata_size = 0;
1612 }
1613 }
1614 }
1615
1616 // for video we need a decoder to get desired information into codec context
1617 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->codec->extradata &&
1618 (!st->codec->width || st->codec->pix_fmt == PIX_FMT_NONE))
1619 {
1620 // open a decoder, it will be cleared down by ffmpeg on closing the stream
1621 if (!st->codec->codec)
1622 {
1623 const AVCodec* codec;
1624 AVDictionary *thread_opt = NULL;
1625 codec = avcodec_find_decoder(st->codec->codec_id);
1626 // Force thread count to 1 since the h264 decoder will not extract
1627 // SPS and PPS to extradata during multi-threaded decoding
1628 av_dict_set(&thread_opt, "threads", "1", 0);
1629 int res = avcodec_open2(st->codec, codec, &thread_opt);
1630 if(res < 0)
1631 CLog::Log(LOGERROR, "CDVDDemuxFFmpeg::ParsePacket() unable to open codec %d", res);
1632 av_dict_free(&thread_opt);
1633 }
1634
1635 // We don't need to actually decode here
1636 // we just want to transport SPS data into codec context
1637 st->codec->skip_idct = AVDISCARD_ALL;
1638 // extradata is not decoded if skip_frame >= AVDISCARD_NONREF
1639// st->codec->skip_frame = AVDISCARD_ALL;
1640 st->codec->skip_loop_filter = AVDISCARD_ALL;
1641
1642 // We are looking for an IDR frame
1643 AVFrame picture;
1644 memset(&picture, 0, sizeof(AVFrame));
1645 picture.pts = picture.pkt_dts = picture.pkt_pts = picture.best_effort_timestamp = AV_NOPTS_VALUE;
1646 picture.pkt_pos = -1;
1647 picture.key_frame = 1;
1648 picture.format = -1;
1649
1650 int got_picture = 0;
1651 avcodec_decode_video2(st->codec, &picture, &got_picture, pkt);
1652 }
1653}
1654
1655bool CDVDDemuxFFmpeg::IsVideoReady()
1656{
1657 AVStream *st;
1658 bool hasVideo = false;
1659
1660 if(!m_checkvideo)
1661 return true;
1662
1663 if (m_program == 0 && !m_pFormatContext->nb_programs)
1664 return false;
1665
1666 if(m_program != UINT_MAX)
1667 {
1668 for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++)
1669 {
1670 int idx = m_pFormatContext->programs[m_program]->stream_index[i];
1671 st = m_pFormatContext->streams[idx];
1672 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
1673 {
1674 if (st->codec->width && st->codec->pix_fmt != PIX_FMT_NONE)
1675 return true;
1676 hasVideo = true;
1677 }
1678 }
1679 }
1680 else
1681 {
1682 for (unsigned int i = 0; i < m_pFormatContext->nb_streams; i++)
1683 {
1684 st = m_pFormatContext->streams[i];
1685 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
1686 {
1687 if (st->codec->width && st->codec->pix_fmt != PIX_FMT_NONE)
1688 return true;
1689 hasVideo = true;
1690 }
1691 }
1692 }
1693 return !hasVideo;
1694}
1695
1696void CDVDDemuxFFmpeg::ResetVideoStreams()
1697{
1698 AVStream *st;
1699 for (unsigned int i = 0; i < m_pFormatContext->nb_streams; i++)
1700 {
1701 st = m_pFormatContext->streams[i];
1702 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
1703 {
1704 if (st->codec->extradata)
1705 av_free(st->codec->extradata);
1706 st->codec->extradata = NULL;
1707 st->codec->width = 0;
1708 }
1709 }
1710}
1711
1712void CDVDDemuxFFmpeg::GetL16Parameters(int &channels, int &samplerate)
1713{
1714 std::string content;
1715 if (XFILE::CCurlFile::GetContentType(m_pInput->GetURL(), content))
1716 {
1717 StringUtils::ToLower(content);
1718 const size_t len = content.length();
1719 size_t pos = content.find(';');
1720 while (pos < len)
1721 {
1722 // move to the next non-whitespace character
1723 pos = content.find_first_not_of(" \t", pos + 1);
1724
1725 if (pos != std::string::npos)
1726 {
1727 if (content.compare(pos, 9, "channels=", 9) == 0)
1728 {
1729 pos += 9; // move position to char after 'channels='
1730 size_t len = content.find(';', pos);
1731 if (len != std::string::npos)
1732 len -= pos;
1733 std::string no_channels(content, pos, len);
1734 // as we don't support any charset with ';' in name
1735 StringUtils::Trim(no_channels, " \t");
1736 if (!no_channels.empty())
1737 {
1738 int val = strtol(no_channels.c_str(), NULL, 0);
1739 if (val > 0)
1740 channels = val;
1741 else
1742 CLog::Log(LOGDEBUG, "CDVDDemuxFFmpeg::%s - no parameter for channels", __FUNCTION__);
1743 }
1744 }
1745 else if (content.compare(pos, 5, "rate=", 5) == 0)
1746 {
1747 pos += 5; // move position to char after 'rate='
1748 size_t len = content.find(';', pos);
1749 if (len != std::string::npos)
1750 len -= pos;
1751 std::string rate(content, pos, len);
1752 // as we don't support any charset with ';' in name
1753 StringUtils::Trim(rate, " \t");
1754 if (!rate.empty())
1755 {
1756 int val = strtol(rate.c_str(), NULL, 0);
1757 if (val > 0)
1758 samplerate = val;
1759 else
1760 CLog::Log(LOGDEBUG, "CDVDDemuxFFmpeg::%s - no parameter for samplerate", __FUNCTION__);
1761 }
1762 }
1763 pos = content.find(';', pos); // find next parameter
1764 }
1765 }
1766 }
1767}