+++ /dev/null
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "system.h"
-
-#include "AMLPlayer.h"
-#include "Application.h"
-#include "FileItem.h"
-#include "FileURLProtocol.h"
-#include "GUIInfoManager.h"
-#include "video/VideoThumbLoader.h"
-#include "Util.h"
-#include "cores/AudioEngine/AEFactory.h"
-#include "cores/AudioEngine/Utils/AEUtil.h"
-#include "cores/VideoRenderers/RenderFlags.h"
-#include "cores/VideoRenderers/RenderFormats.h"
-#include "cores/VideoRenderers/RenderManager.h"
-#include "dialogs/GUIDialogKaiToast.h"
-#include "filesystem/File.h"
-#include "filesystem/SpecialProtocol.h"
-#include "guilib/GUIWindowManager.h"
-#include "guilib/LocalizeStrings.h"
-#include "settings/AdvancedSettings.h"
-#include "settings/VideoSettings.h"
-#include "settings/MediaSettings.h"
-#include "settings/Settings.h"
-#include "threads/SingleLock.h"
-#include "utils/log.h"
-#include "utils/TimeUtils.h"
-#include "utils/URIUtils.h"
-#include "utils/LangCodeExpander.h"
-#include "utils/Variant.h"
-#include "windowing/WindowingFactory.h"
-
-// for external subtitles
-#include "xbmc/cores/dvdplayer/DVDClock.h"
-#include "xbmc/cores/dvdplayer/DVDPlayerSubtitle.h"
-#include "xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxVobsub.h"
-#include "settings/VideoSettings.h"
-
-// amlogic libplayer
-#include "utils/AMLUtils.h"
-#include "DllLibamplayer.h"
-
-static float VolumePercentToScale(float volume)
-{
- float audio_volume = 0.0;
- if (volume > VOLUME_MINIMUM)
- {
- float dB = CAEUtil::PercentToGain(volume);
- audio_volume = CAEUtil::GainToScale(dB);
- }
- if (audio_volume >= 0.99f)
- audio_volume = 1.0f;
-
- return audio_volume;
-}
-
-struct AMLChapterInfo
-{
- std::string name;
- int64_t seekto_ms;
-};
-
-struct AMLPlayerStreamInfo
-{
- void Clear()
- {
- id = 0;
- width = 0;
- height = 0;
- aspect_ratio_num = 0;
- aspect_ratio_den = 0;
- frame_rate_num = 0;
- frame_rate_den = 0;
- bit_rate = 0;
- duration = 0;
- channel = 0;
- sample_rate = 0;
- language = "";
- type = STREAM_NONE;
- source = STREAM_SOURCE_NONE;
- name = "";
- filename = "";
- filename2 = "";
- }
-
- int id;
- StreamType type;
- StreamSource source;
- int width;
- int height;
- int aspect_ratio_num;
- int aspect_ratio_den;
- int frame_rate_num;
- int frame_rate_den;
- int bit_rate;
- int duration;
- int channel;
- int sample_rate;
- int format;
- std::string language;
- std::string name;
- std::string filename;
- std::string filename2; // for vobsub subtitles, 2 files are necessary (idx/sub)
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////
-static int media_info_dump(media_info_t* minfo)
-{
- int i = 0;
- CLog::Log(LOGDEBUG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
- CLog::Log(LOGDEBUG, "======||file size:%lld", minfo->stream_info.file_size);
- CLog::Log(LOGDEBUG, "======||file type:%d", minfo->stream_info.type);
- CLog::Log(LOGDEBUG, "======||duration:%d", minfo->stream_info.duration);
- CLog::Log(LOGDEBUG, "======||has video track?:%s", minfo->stream_info.has_video>0?"YES!":"NO!");
- CLog::Log(LOGDEBUG, "======||has audio track?:%s", minfo->stream_info.has_audio>0?"YES!":"NO!");
- CLog::Log(LOGDEBUG, "======||has internal subtitle?:%s", minfo->stream_info.has_sub>0?"YES!":"NO!");
- CLog::Log(LOGDEBUG, "======||internal subtile counts:%d", minfo->stream_info.total_sub_num);
- if (minfo->stream_info.has_video && minfo->stream_info.total_video_num > 0)
- {
- CLog::Log(LOGDEBUG, "======||video index:%d", minfo->stream_info.cur_video_index);
- CLog::Log(LOGDEBUG, "======||video counts:%d", minfo->stream_info.total_video_num);
- CLog::Log(LOGDEBUG, "======||video width :%d", minfo->video_info[0]->width);
- CLog::Log(LOGDEBUG, "======||video height:%d", minfo->video_info[0]->height);
- CLog::Log(LOGDEBUG, "======||video ratio :%d:%d", minfo->video_info[0]->aspect_ratio_num,minfo->video_info[0]->aspect_ratio_den);
- CLog::Log(LOGDEBUG, "======||frame_rate :%.2f", (float)minfo->video_info[0]->frame_rate_num/minfo->video_info[0]->frame_rate_den);
- CLog::Log(LOGDEBUG, "======||video bitrate:%d", minfo->video_info[0]->bit_rate);
- CLog::Log(LOGDEBUG, "======||video format:%d", minfo->video_info[0]->format);
- CLog::Log(LOGDEBUG, "======||video duration:%d", minfo->video_info[0]->duartion);
- }
- if (minfo->stream_info.has_audio && minfo->stream_info.total_audio_num > 0)
- {
- CLog::Log(LOGDEBUG, "======||audio index:%d", minfo->stream_info.cur_audio_index);
- CLog::Log(LOGDEBUG, "======||audio counts:%d", minfo->stream_info.total_audio_num);
- for (i = 0; i < minfo->stream_info.total_audio_num; i++)
- {
- CLog::Log(LOGDEBUG, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
- CLog::Log(LOGDEBUG, "======||audio track(%d) id:%d", i, minfo->audio_info[i]->id);
- CLog::Log(LOGDEBUG, "======||audio track(%d) codec type:%d", i, minfo->audio_info[i]->aformat);
- CLog::Log(LOGDEBUG, "======||audio track(%d) audio_channel:%d", i, minfo->audio_info[i]->channel);
- CLog::Log(LOGDEBUG, "======||audio track(%d) bit_rate:%d", i, minfo->audio_info[i]->bit_rate);
- CLog::Log(LOGDEBUG, "======||audio track(%d) audio_samplerate:%d", i, minfo->audio_info[i]->sample_rate);
- CLog::Log(LOGDEBUG, "======||audio track(%d) duration:%d", i, minfo->audio_info[i]->duration);
- CLog::Log(LOGDEBUG, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
- if (NULL != minfo->audio_info[i]->audio_tag)
- {
- CLog::Log(LOGDEBUG, "======||audio track title:%s", minfo->audio_info[i]->audio_tag->title!=NULL?minfo->audio_info[i]->audio_tag->title:"unknown");
- CLog::Log(LOGDEBUG, "======||audio track album:%s", minfo->audio_info[i]->audio_tag->album!=NULL?minfo->audio_info[i]->audio_tag->album:"unknown");
- CLog::Log(LOGDEBUG, "======||audio track author:%s", minfo->audio_info[i]->audio_tag->author!=NULL?minfo->audio_info[i]->audio_tag->author:"unknown");
- CLog::Log(LOGDEBUG, "======||audio track year:%s", minfo->audio_info[i]->audio_tag->year!=NULL?minfo->audio_info[i]->audio_tag->year:"unknown");
- CLog::Log(LOGDEBUG, "======||audio track comment:%s", minfo->audio_info[i]->audio_tag->comment!=NULL?minfo->audio_info[i]->audio_tag->comment:"unknown");
- CLog::Log(LOGDEBUG, "======||audio track genre:%s", minfo->audio_info[i]->audio_tag->genre!=NULL?minfo->audio_info[i]->audio_tag->genre:"unknown");
- CLog::Log(LOGDEBUG, "======||audio track copyright:%s", minfo->audio_info[i]->audio_tag->copyright!=NULL?minfo->audio_info[i]->audio_tag->copyright:"unknown");
- CLog::Log(LOGDEBUG, "======||audio track track:%d", minfo->audio_info[i]->audio_tag->track);
- }
- }
- }
- if (minfo->stream_info.has_sub && minfo->stream_info.total_sub_num > 0)
- {
- CLog::Log(LOGDEBUG, "======||subtitle index:%d", minfo->stream_info.cur_sub_index);
- CLog::Log(LOGDEBUG, "======||subtitle counts:%d", minfo->stream_info.total_sub_num);
- for (i = 0; i < minfo->stream_info.total_sub_num; i++)
- {
- if (0 == minfo->sub_info[i]->internal_external){
- CLog::Log(LOGDEBUG, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
- CLog::Log(LOGDEBUG, "======||internal subtitle(%d) pid:%d", i, minfo->sub_info[i]->id);
- CLog::Log(LOGDEBUG, "======||internal subtitle(%d) language:%s", i, minfo->sub_info[i]->sub_language?minfo->sub_info[i]->sub_language:"unknown");
- CLog::Log(LOGDEBUG, "======||internal subtitle(%d) width:%d", i, minfo->sub_info[i]->width);
- CLog::Log(LOGDEBUG, "======||internal subtitle(%d) height:%d", i, minfo->sub_info[i]->height);
- CLog::Log(LOGDEBUG, "======||internal subtitle(%d) resolution:%d", i, minfo->sub_info[i]->resolution);
- CLog::Log(LOGDEBUG, "======||internal subtitle(%d) subtitle size:%lld", i, minfo->sub_info[i]->subtitle_size);
- CLog::Log(LOGDEBUG, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
- }
- }
- }
- CLog::Log(LOGDEBUG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
- return 0;
-}
-
-static const char* VideoCodecName(int vformat)
-{
- const char *format = "";
-
- switch(vformat)
- {
- case VFORMAT_MPEG12:
- format = "mpeg12";
- break;
- case VFORMAT_MPEG4:
- format = "mpeg4";
- break;
- case VFORMAT_H264:
- format = "h264";
- break;
- case VFORMAT_MJPEG:
- format = "mjpeg";
- break;
- case VFORMAT_REAL:
- format = "real";
- break;
- case VFORMAT_JPEG:
- format = "jpeg";
- break;
- case VFORMAT_VC1:
- format = "vc1";
- break;
- case VFORMAT_AVS:
- format = "avs";
- break;
- case VFORMAT_SW:
- format = "sw";
- break;
- case VFORMAT_H264MVC:
- format = "h264mvc";
- break;
- default:
- format = "unknown";
- break;
- }
- return format;
-}
-
-static const char* AudioCodecName(int aformat)
-{
- const char *format = "";
-
- switch(aformat)
- {
- case AFORMAT_MPEG:
- format = "mpeg";
- break;
- case AFORMAT_PCM_S16LE:
- format = "pcm";
- break;
- case AFORMAT_AAC:
- format = "aac";
- break;
- case AFORMAT_AC3:
- format = "ac3";
- break;
- case AFORMAT_ALAW:
- format = "alaw";
- break;
- case AFORMAT_MULAW:
- format = "mulaw";
- break;
- case AFORMAT_DTS:
- format = "dts";
- break;
- case AFORMAT_PCM_S16BE:
- format = "pcm";
- break;
- case AFORMAT_FLAC:
- format = "flac";
- break;
- case AFORMAT_COOK:
- format = "cook";
- break;
- case AFORMAT_PCM_U8:
- format = "pcm";
- break;
- case AFORMAT_ADPCM:
- format = "adpcm";
- break;
- case AFORMAT_AMR:
- format = "amr";
- break;
- case AFORMAT_RAAC:
- format = "raac";
- break;
- case AFORMAT_WMA:
- format = "wma";
- break;
- case AFORMAT_WMAPRO:
- format = "wmapro";
- break;
- case AFORMAT_PCM_BLURAY:
- format = "lpcm";
- break;
- case AFORMAT_ALAC:
- format = "alac";
- break;
- case AFORMAT_VORBIS:
- format = "vorbis";
- break;
- case AFORMAT_AAC_LATM:
- format = "aac-latm";
- break;
- case AFORMAT_APE:
- format = "ape";
- break;
- default:
- format = "unknown";
- break;
- }
-
- return format;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-CAMLSubTitleThread::CAMLSubTitleThread(DllLibAmplayer *dll) :
- CThread("AMLSubTitle"),
- m_dll(dll),
- m_subtitle_codec(-1)
-{
-}
-
-CAMLSubTitleThread::~CAMLSubTitleThread()
-{
- StopThread();
-}
-
-void CAMLSubTitleThread::Flush()
-{
- CSingleLock lock(m_subtitle_csection);
- m_subtitle_strings.clear();
-}
-
-void CAMLSubTitleThread::UpdateSubtitle(CStdString &subtitle, int64_t elapsed_ms)
-{
- CSingleLock lock(m_subtitle_csection);
- if (!m_subtitle_strings.empty())
- {
- AMLSubtitle *amlsubtitle;
- // remove any expired subtitles
- std::deque<AMLSubtitle*>::iterator it = m_subtitle_strings.begin();
- while (it != m_subtitle_strings.end())
- {
- amlsubtitle = *it;
- if (elapsed_ms > amlsubtitle->endtime)
- it = m_subtitle_strings.erase(it);
- else
- ++it;
- }
-
- // find the current subtitle
- it = m_subtitle_strings.begin();
- while (it != m_subtitle_strings.end())
- {
- amlsubtitle = *it;
- if (elapsed_ms > amlsubtitle->bgntime && elapsed_ms < amlsubtitle->endtime)
- {
- subtitle = amlsubtitle->string;
- break;
- }
- ++it;
- }
- }
-}
-
-void CAMLSubTitleThread::Process(void)
-{
- CLog::Log(LOGDEBUG, "CAMLSubTitleThread::Process begin");
-
- m_subtitle_codec = m_dll->codec_open_sub_read();
- if (m_subtitle_codec < 0)
- CLog::Log(LOGERROR, "CAMLSubTitleThread::Process: codec_open_sub_read failed");
-
- while (!m_bStop)
- {
- if (m_subtitle_codec > 0)
- {
- // poll sub codec, we return on timeout or when a sub gets loaded
- // TODO: codec_poll_sub_fd has a bug in kernel driver, it trashes
- // subs in certain conditions so we read garbage, manual poll for now.
- //codec_poll_sub_fd(m_subtitle_codec, 1000);
- int sub_size = m_dll->codec_get_sub_size_fd(m_subtitle_codec);
- if (sub_size > 0)
- {
- // calloc sub_size + 1 so we auto terminate the string
- char *sub_buffer = (char*)calloc(sub_size + 1, 1);
- m_dll->codec_read_sub_data_fd(m_subtitle_codec, sub_buffer, sub_size);
-
- // check subtitle header stamp
- if ((sub_buffer[0] == 0x41) && (sub_buffer[1] == 0x4d) &&
- (sub_buffer[2] == 0x4c) && (sub_buffer[3] == 0x55) &&
- (sub_buffer[4] == 0xaa))
- {
- // 20 byte header, then subtitle string
- if (sub_size >= 20)
- {
- // csection lock it now as we are diddling shared vars
- CSingleLock lock(m_subtitle_csection);
-
- AMLSubtitle *subtitle = new AMLSubtitle;
-
- int sub_type = (sub_buffer[5] << 16) | (sub_buffer[6] << 8) | sub_buffer[7];
- // sub_pts are in ffmpeg timebase, not ms timebase, convert it.
- int sub_pts = (sub_buffer[12] << 24) | (sub_buffer[13] << 16) | (sub_buffer[14] << 8) | sub_buffer[15];
-
- /* TODO: handle other subtitle codec types
- // subtitle codecs
- AV_CODEC_ID_DVD_SUBTITLE= 0x17000,
- AV_CODEC_ID_DVB_SUBTITLE,
- AV_CODEC_ID_TEXT, ///< raw UTF-8 text
- AV_CODEC_ID_XSUB,
- AV_CODEC_ID_SSA,
- AV_CODEC_ID_MOV_TEXT,
- AV_CODEC_ID_HDMV_PGS_SUBTITLE,
- AV_CODEC_ID_DVB_TELETEXT,
- AV_CODEC_ID_SRT,
- AV_CODEC_ID_MICRODVD,
- */
- switch(sub_type)
- {
- default:
- CLog::Log(LOGDEBUG, "CAMLSubTitleThread::Process: fixme :) "
- "sub_type(0x%x), size(%d), bgntime(%lld), endtime(%lld), string(%s)",
- sub_type, sub_size-20, subtitle->bgntime, subtitle->endtime, &sub_buffer[20]);
- break;
- case AV_CODEC_ID_TEXT:
- subtitle->bgntime = sub_pts/ 90;
- subtitle->endtime = subtitle->bgntime + 4000;
- subtitle->string = &sub_buffer[20];
- break;
- case AV_CODEC_ID_SSA:
- if (strncmp((const char*)&sub_buffer[20], "Dialogue:", 9) == 0)
- {
- int vars_found, hour1, min1, sec1, hunsec1, hour2, min2, sec2, hunsec2, nothing;
- char line3[sub_size];
- char *line = &sub_buffer[20];
-
- memset(line3, 0x00, sub_size);
- vars_found = sscanf(line, "Dialogue: Marked=%d,%d:%d:%d.%d,%d:%d:%d.%d,%[^\n\r]",
- ¬hing, &hour1, &min1, &sec1, &hunsec1, &hour2, &min2, &sec2, &hunsec2, line3);
- if (vars_found < 10)
- vars_found = sscanf(line, "Dialogue: %d,%d:%d:%d.%d,%d:%d:%d.%d,%[^\n\r]",
- ¬hing, &hour1, &min1, &sec1, &hunsec1, &hour2, &min2, &sec2, &hunsec2, line3);
-
- if (vars_found > 9)
- {
- char *tmp, *line2 = strchr(line3, ',');
- // use 32 for the case that the amount of commas increase with newer SSA versions
- for (int comma = 4; comma < 32; comma++)
- {
- tmp = strchr(line2 + 1, ',');
- if (!tmp)
- break;
- if (*(++tmp) == ' ')
- break;
- // a space after a comma means we are already in a sentence
- line2 = tmp;
- }
- // eliminate the trailing comma
- if (*line2 == ',')
- line2++;
- subtitle->bgntime = 10 * (360000 * hour1 + 6000 * min1 + 100 * sec1 + hunsec1);
- subtitle->endtime = 10 * (360000 * hour2 + 6000 * min2 + 100 * sec2 + hunsec2);
- subtitle->string = line2;
- // convert tags to what we understand
- if (subtitle->string.Replace("{\\i1}","[I]"))
- subtitle->string.Replace("{\\i0}","[/I]");
- if (subtitle->string.Replace("{\\b1}","[B]"))
- subtitle->string.Replace("{\\b0}","[/B]");
- // remove anything other tags
- for (std::string::const_iterator it = subtitle->string.begin(); it != subtitle->string.end(); ++it)
- {
- size_t beg = subtitle->string.find("{\\");
- if (beg != std::string::npos)
- {
- size_t end = subtitle->string.find("}", beg);
- if (end != std::string::npos)
- subtitle->string.erase(beg, end-beg+1);
- }
- }
- }
- }
- break;
- }
- free(sub_buffer);
-
- if (subtitle->string.length())
- {
- // quirks
- subtitle->string.Replace("'","\'");
- m_subtitle_strings.push_back(subtitle);
- // fixup existing endtimes so they do not exceed bgntime of previous subtitle
- for (size_t i = 0; i < m_subtitle_strings.size() - 1; i++)
- {
- if (m_subtitle_strings[i]->endtime > m_subtitle_strings[i+1]->bgntime)
- m_subtitle_strings[i]->endtime = m_subtitle_strings[i+1]->bgntime;
- }
- }
- }
- }
- }
- else
- {
- if (!m_bStop)
- usleep(100 * 1000);
- }
- }
- else
- {
- if (!m_bStop)
- usleep(250 * 1000);
- }
- }
- m_subtitle_strings.clear();
- if (m_subtitle_codec > 0)
- m_dll->codec_close_sub_fd(m_subtitle_codec);
- m_subtitle_codec = -1;
-
- CLog::Log(LOGDEBUG, "CAMLSubTitleThread::Process end");
-}
-////////////////////////////////////////////////////////////////////////////////////////////
-CAMLPlayer::CAMLPlayer(IPlayerCallback &callback)
- : IPlayer(callback),
- CThread ("AMLPlayer" ),
- m_cpu (0 ),
- m_speed (0 ),
- m_paused (false ),
- m_bAbortRequest (false ),
- m_ready (true ),
- m_audio_index (0 ),
- m_audio_count (0 ),
- m_audio_delay (0 ),
- m_audio_passthrough_ac3 (false ),
- m_audio_passthrough_dts (false ),
- m_audio_mute (false ),
- m_audio_volume (0.0f ),
- m_video_index (0 ),
- m_video_count (0 ),
- m_video_width (0 ),
- m_video_height (0 ),
- m_video_fps_numerator (0 ),
- m_video_fps_denominator (0 ),
- m_subtitle_index (0 ),
- m_subtitle_count (0 ),
- m_subtitle_show (false ),
- m_subtitle_delay (0 ),
- m_subtitle_thread (NULL ),
- m_chapter_count (0 ),
- m_show_mainvideo (0 ),
- m_view_mode (0 ),
- m_zoom (0 ),
- m_contrast (0 ),
- m_brightness (0 )
-{
- m_dll = new DllLibAmplayer;
- m_dll->Load();
- m_pid = -1;
-#if defined(_DEBUG)
- m_log_level = 5;
-#else
- m_log_level = 3;
-#endif
-
- // for external subtitles
- m_dvdOverlayContainer = new CDVDOverlayContainer;
- m_dvdPlayerSubtitle = new CDVDPlayerSubtitle(m_dvdOverlayContainer);
-
- // Suspend AE temporarily so exclusive or hog-mode sinks
- // don't block external player's access to audio device
- if (!CAEFactory::Suspend())
- {
- CLog::Log(LOGNOTICE,"%s: Failed to suspend AudioEngine before launching external player", __FUNCTION__);
- }
-}
-
-CAMLPlayer::~CAMLPlayer()
-{
- CloseFile();
-
- delete m_dvdPlayerSubtitle;
- delete m_dvdOverlayContainer;
- delete m_dll, m_dll = NULL;
-
- // Resume AE processing of XBMC native audio
- if (!CAEFactory::Resume())
- {
- CLog::Log(LOGFATAL, "%s: Failed to restart AudioEngine after return from external player",__FUNCTION__);
- }
-}
-
-bool CAMLPlayer::OpenFile(const CFileItem &file, const CPlayerOptions &options)
-{
- try
- {
- CLog::Log(LOGNOTICE, "CAMLPlayer: Opening: %s", file.GetPath().c_str());
- // if playing a file close it first
- // this has to be changed so we won't have to close it.
- if (IsRunning())
- CloseFile();
-
- m_bAbortRequest = false;
-
- m_item = file;
- m_options = options;
-
- m_pid = -1;
- m_elapsed_ms = 0;
- m_duration_ms = 0;
-
- m_audio_info = "none";
- m_audio_delay = 0;
- m_audio_mute = CAEFactory::IsMuted();
- m_audio_volume = VolumePercentToScale(CAEFactory::GetVolume());
- m_audio_passthrough_ac3 = CSettings::Get().GetBool("audiooutput.ac3passthrough");
- m_audio_passthrough_dts = CSettings::Get().GetBool("audiooutput.dtspassthrough");
-
- m_video_info = "none";
- m_video_width = 0;
- m_video_height = 0;
- m_video_fps_numerator = 25;
- m_video_fps_denominator = 1;
-
- m_subtitle_delay = 0;
- m_subtitle_thread = NULL;
-
- m_chapter_count = 0;
-
- m_show_mainvideo = -1;
- m_dst_rect.SetRect(0, 0, 0, 0);
- m_zoom = -1;
- m_contrast = -1;
- m_brightness = -1;
-
- ClearStreamInfos();
-
- if (m_item.IsDVDFile() || m_item.IsDVD())
- return false;
-
- // setup to spin the busy dialog until we are playing
- m_ready.Reset();
-
- g_renderManager.PreInit();
-
- // create the playing thread
- Create();
- if (!m_ready.WaitMSec(100))
- {
- CGUIDialogBusy *dialog = (CGUIDialogBusy*)g_windowManager.GetWindow(WINDOW_DIALOG_BUSY);
- dialog->Show();
- while (!m_ready.WaitMSec(1))
- g_windowManager.ProcessRenderLoop(false);
- dialog->Close();
- }
-
- // Playback might have been stopped due to some error.
- if (m_bStop || m_bAbortRequest)
- return false;
-
- return true;
- }
- catch (...)
- {
- CLog::Log(LOGERROR, "%s - Exception thrown on open", __FUNCTION__);
- return false;
- }
-}
-
-bool CAMLPlayer::CloseFile()
-{
- CLog::Log(LOGDEBUG, "CAMLPlayer::CloseFile");
-
- // set the abort request so that other threads can finish up
- m_bAbortRequest = true;
-
- CLog::Log(LOGDEBUG, "CAMLPlayer: waiting for threads to exit");
- // wait for the main thread to finish up
- // since this main thread cleans up all other resources and threads
- // we are done after the StopThread call
- StopThread();
-
- CLog::Log(LOGDEBUG, "CAMLPlayer: finished waiting");
-
- g_renderManager.UnInit();
-
- return true;
-}
-
-bool CAMLPlayer::IsPlaying() const
-{
- return !m_bStop;
-}
-
-void CAMLPlayer::Pause()
-{
- CLog::Log(LOGDEBUG, "CAMLPlayer::Pause");
- CSingleLock lock(m_aml_csection);
-
- if ((m_pid < 0) && m_bAbortRequest)
- return;
-
- if (m_paused)
- m_dll->player_resume(m_pid);
- else
- m_dll->player_pause(m_pid);
-
- m_paused = !m_paused;
-}
-
-bool CAMLPlayer::IsPaused() const
-{
- return m_paused;
-}
-
-bool CAMLPlayer::HasVideo() const
-{
- return m_video_count > 0;
-}
-
-bool CAMLPlayer::HasAudio() const
-{
- return m_audio_count > 0;
-}
-
-void CAMLPlayer::ToggleFrameDrop()
-{
- CLog::Log(LOGDEBUG, "CAMLPlayer::ToggleFrameDrop");
-}
-
-bool CAMLPlayer::CanSeek()
-{
- return GetTotalTime() > 0;
-}
-
-void CAMLPlayer::Seek(bool bPlus, bool bLargeStep, bool bChapterOverride)
-{
- // force updated to m_elapsed_ms, m_duration_ms.
- GetStatus();
-
- CSingleLock lock(m_aml_csection);
-
- // try chapter seeking first, chapter_index is ones based.
- int chapter_index = GetChapter();
- if (bLargeStep && bChapterOverride && chapter_index > 0)
- {
- if (!bPlus)
- {
- // seek to previous chapter
- SeekChapter(chapter_index - 1);
- return;
- }
- else if (chapter_index < GetChapterCount())
- {
- // seek to next chapter
- SeekChapter(chapter_index + 1);
- return;
- }
- }
-
- int64_t seek_ms;
- if (g_advancedSettings.m_videoUseTimeSeeking)
- {
- if (bLargeStep && (GetTotalTime() > (2000 * g_advancedSettings.m_videoTimeSeekForwardBig)))
- seek_ms = bPlus ? g_advancedSettings.m_videoTimeSeekForwardBig : g_advancedSettings.m_videoTimeSeekBackwardBig;
- else
- seek_ms = bPlus ? g_advancedSettings.m_videoTimeSeekForward : g_advancedSettings.m_videoTimeSeekBackward;
- // convert to milliseconds
- seek_ms *= 1000;
- seek_ms += m_elapsed_ms;
- }
- else
- {
- float percent;
- if (bLargeStep)
- percent = bPlus ? g_advancedSettings.m_videoPercentSeekForwardBig : g_advancedSettings.m_videoPercentSeekBackwardBig;
- else
- percent = bPlus ? g_advancedSettings.m_videoPercentSeekForward : g_advancedSettings.m_videoPercentSeekBackward;
- percent /= 100.0f;
- percent += (float)m_elapsed_ms/(float)m_duration_ms;
- // convert to milliseconds
- seek_ms = m_duration_ms * percent;
- }
-
- // handle stacked videos, dvdplayer does it so we do it too.
- if (g_application.CurrentFileItem().IsStack() &&
- (seek_ms > m_duration_ms || seek_ms < 0))
- {
- CLog::Log(LOGDEBUG, "CAMLPlayer::Seek: In mystery code, what did I do");
- g_application.SeekTime((seek_ms - m_elapsed_ms) * 0.001 + g_application.GetTime());
- // warning, don't access any object variables here as
- // the object may have been destroyed
- return;
- }
-
- if (seek_ms <= 1000)
- seek_ms = 1000;
-
- if (seek_ms > m_duration_ms)
- seek_ms = m_duration_ms;
-
- // do seek here
- g_infoManager.SetDisplayAfterSeek(100000);
- SeekTime(seek_ms);
- m_callback.OnPlayBackSeek((int)seek_ms, (int)(seek_ms - m_elapsed_ms));
- g_infoManager.SetDisplayAfterSeek();
-}
-
-bool CAMLPlayer::SeekScene(bool bPlus)
-{
- CLog::Log(LOGDEBUG, "CAMLPlayer::SeekScene");
- return false;
-}
-
-void CAMLPlayer::SeekPercentage(float fPercent)
-{
- CSingleLock lock(m_aml_csection);
-
- // force updated to m_elapsed_ms, m_duration_ms.
- GetStatus();
-
- if (m_duration_ms)
- {
- int64_t seek_ms = fPercent * m_duration_ms / 100.0;
- if (seek_ms <= 1000)
- seek_ms = 1000;
-
- // do seek here
- g_infoManager.SetDisplayAfterSeek(100000);
- SeekTime(seek_ms);
- m_callback.OnPlayBackSeek((int)seek_ms, (int)(seek_ms - m_elapsed_ms));
- g_infoManager.SetDisplayAfterSeek();
- }
-}
-
-float CAMLPlayer::GetPercentage()
-{
- GetStatus();
- if (m_duration_ms)
- return 100.0f * (float)m_elapsed_ms/(float)m_duration_ms;
- else
- return 0.0f;
-}
-
-void CAMLPlayer::SetMute(bool bOnOff)
-{
- m_audio_mute = bOnOff;
-
-#if defined(HAS_AMLPLAYER_AUDIO_SETVOLUME)
- CSingleLock lock(m_aml_csection);
- if (m_dll->check_pid_valid(m_pid))
- {
- if (m_audio_mute)
- m_dll->audio_set_volume(m_pid, 0.0);
- else
- m_dll->audio_set_volume(m_pid, m_audio_volume);
- }
-#endif
-}
-
-void CAMLPlayer::SetVolume(float volume)
-{
- // volume is a float percent from 0.0 to 1.0
- m_audio_volume = VolumePercentToScale(volume);
-
-#if defined(HAS_AMLPLAYER_AUDIO_SETVOLUME)
- CSingleLock lock(m_aml_csection);
- if (!m_audio_mute && m_dll->check_pid_valid(m_pid))
- m_dll->audio_set_volume(m_pid, m_audio_volume);
-#endif
-}
-
-void CAMLPlayer::GetAudioInfo(CStdString &strAudioInfo)
-{
- CSingleLock lock(m_aml_csection);
- if (m_audio_streams.empty() || m_audio_index > (int)(m_audio_streams.size() - 1))
- return;
-
- strAudioInfo.Format("Audio stream (%s) [Kb/s:%.2f]",
- AudioCodecName(m_audio_streams[m_audio_index]->format),
- (double)m_audio_streams[m_audio_index]->bit_rate / 1024.0);
-}
-
-void CAMLPlayer::GetVideoInfo(CStdString &strVideoInfo)
-{
- CSingleLock lock(m_aml_csection);
- if (m_video_streams.empty() || m_video_index > (int)(m_video_streams.size() - 1))
- return;
-
- strVideoInfo.Format("Video stream (%s) [fr:%.3f Mb/s:%.2f]",
- VideoCodecName(m_video_streams[m_video_index]->format),
- GetActualFPS(),
- (double)m_video_streams[m_video_index]->bit_rate / (1024.0*1024.0));
-}
-
-int CAMLPlayer::GetAudioStreamCount()
-{
- //CLog::Log(LOGDEBUG, "CAMLPlayer::GetAudioStreamCount");
- return m_audio_count;
-}
-
-int CAMLPlayer::GetAudioStream()
-{
- //CLog::Log(LOGDEBUG, "CAMLPlayer::GetAudioStream");
- return m_audio_index;
-}
-
-void CAMLPlayer::SetAudioStream(int SetAudioStream)
-{
- //CLog::Log(LOGDEBUG, "CAMLPlayer::SetAudioStream");
- CSingleLock lock(m_aml_csection);
-
- if (SetAudioStream > (int)m_audio_streams.size() || SetAudioStream < 0)
- return;
-
- m_audio_index = SetAudioStream;
- SetAudioPassThrough(m_audio_streams[m_audio_index]->format);
-
- if (m_dll->check_pid_valid(m_pid))
- {
- m_dll->player_aid(m_pid, m_audio_streams[m_audio_index]->id);
- }
-}
-
-void CAMLPlayer::SetAVDelay(float fValue)
-{
- CLog::Log(LOGDEBUG, "CAMLPlayer::SetAVDelay (%f)", fValue);
- m_audio_delay = fValue * 1000.0;
-
-#if defined(HAS_AMLPLAYER_AUDIO_SETDELAY)
- if (m_audio_streams.size() && m_dll->check_pid_valid(m_pid))
- {
- CSingleLock lock(m_aml_csection);
- m_dll->audio_set_delay(m_pid, m_audio_delay);
- }
-#endif
-}
-
-float CAMLPlayer::GetAVDelay()
-{
- return (float)m_audio_delay / 1000.0;
-}
-
-void CAMLPlayer::SetSubTitleDelay(float fValue = 0.0f)
-{
- if (GetSubtitleCount())
- {
- CSingleLock lock(m_aml_csection);
- m_subtitle_delay = fValue * 1000.0;
- }
-}
-
-float CAMLPlayer::GetSubTitleDelay()
-{
- return (float)m_subtitle_delay / 1000.0;
-}
-
-int CAMLPlayer::GetSubtitleCount()
-{
- return m_subtitle_count;
-}
-
-int CAMLPlayer::GetSubtitle()
-{
- if (m_subtitle_show)
- return m_subtitle_index;
- else
- return -1;
-}
-
-void CAMLPlayer::GetSubtitleStreamInfo(int index, SPlayerSubtitleStreamInfo &info)
-{
- CSingleLock lock(m_aml_csection);
-
- if (index > (int)m_subtitle_streams.size() -1 || index < 0)
- return;
-
- info.language = m_subtitle_streams[index]->language;
- info.name = m_subtitle_streams[m_subtitle_index]->name;
-
- if (m_log_level > 5)
- CLog::Log(LOGDEBUG, "CAMLPlayer::GetSubtitleName, iStream(%d)", index);
-}
-
-void CAMLPlayer::SetSubtitle(int iStream)
-{
- CSingleLock lock(m_aml_csection);
-
- if (iStream > (int)m_subtitle_streams.size() || iStream < 0)
- return;
-
- m_subtitle_index = iStream;
-
- // smells like a bug, if no showing subs and we get called
- // to set the subtitle, we are expected to update internal state
- // but not show the subtitle.
- if (!m_subtitle_show)
- return;
-
- if (m_dll->check_pid_valid(m_pid) && m_subtitle_streams[m_subtitle_index]->source == STREAM_SOURCE_NONE)
- {
- m_dll->player_sid(m_pid, m_subtitle_streams[m_subtitle_index]->id);
- aml_set_sysfs_int("/sys/class/subtitle/curr", m_subtitle_index);
- if (m_subtitle_thread)
- m_subtitle_thread->Flush();
- }
- else
- {
- m_dvdPlayerSubtitle->CloseStream(true);
- OpenSubtitleStream(m_subtitle_index);
- }
-}
-
-bool CAMLPlayer::GetSubtitleVisible()
-{
- return m_subtitle_show;
-}
-
-void CAMLPlayer::SetSubtitleVisible(bool bVisible)
-{
- m_subtitle_show = (bVisible && m_subtitle_count);
- CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleOn = bVisible;
-
- if (m_subtitle_show && m_subtitle_count)
- {
- if (CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleStream < m_subtitle_count)
- m_subtitle_index = CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleStream;
- // on startup, if asked to show subs and SetSubtitle has not
- // been called, we are expected to switch/show the 1st subtitle
- if (m_subtitle_index < 0)
- m_subtitle_index = 0;
- if (m_dll->check_pid_valid(m_pid) && m_subtitle_streams[m_subtitle_index]->source == STREAM_SOURCE_NONE)
- {
- m_dll->player_sid(m_pid, m_subtitle_streams[m_subtitle_index]->id);
- aml_set_sysfs_int("/sys/class/subtitle/curr", m_subtitle_index);
- if (m_subtitle_thread)
- m_subtitle_thread->Flush();
- }
- else
- OpenSubtitleStream(m_subtitle_index);
- }
-}
-
-int CAMLPlayer::AddSubtitle(const CStdString& strSubPath)
-{
- CSingleLock lock(m_aml_csection);
-
- return AddSubtitleFile(strSubPath);
-}
-
-void CAMLPlayer::GetVideoRect(CRect& SrcRect, CRect& DestRect)
-{
- g_renderManager.GetVideoRect(SrcRect, DestRect);
-}
-
-void CAMLPlayer::GetVideoAspectRatio(float &fAR)
-{
- fAR = g_renderManager.GetAspectRatio();
-}
-
-int CAMLPlayer::GetChapterCount()
-{
- return m_chapter_count;
-}
-
-int CAMLPlayer::GetChapter()
-{
- // returns a one based value or zero if no chapters
- GetStatus();
-
- int chapter_index = -1;
- for (int i = 0; i < m_chapter_count; i++)
- {
- if (m_elapsed_ms >= m_chapters[i]->seekto_ms)
- chapter_index = i;
- }
- return chapter_index + 1;
-}
-
-void CAMLPlayer::GetChapterName(CStdString& strChapterName)
-{
- if (m_chapter_count)
- strChapterName = m_chapters[GetChapter() - 1]->name;
-}
-
-int CAMLPlayer::SeekChapter(int chapter_index)
-{
- CSingleLock lock(m_aml_csection);
-
- // chapter_index is a one based value.
- if (m_chapter_count > 1)
- {
- if (chapter_index < 1)
- chapter_index = 1;
- if (chapter_index > m_chapter_count)
- return 0;
-
- // time units are seconds,
- // so we add 1000ms to get into the chapter.
- int64_t seek_ms = m_chapters[chapter_index - 1]->seekto_ms + 1000;
-
- // seek to 1 second and play is immediate.
- if (seek_ms <= 0)
- seek_ms = 1000;
-
- // seek to chapter here
- g_infoManager.SetDisplayAfterSeek(100000);
- SeekTime(seek_ms);
- m_callback.OnPlayBackSeekChapter(chapter_index);
- g_infoManager.SetDisplayAfterSeek();
- }
- else
- {
- // we do not have a chapter list so do a regular big jump.
- if (chapter_index > 0)
- Seek(true, true);
- else
- Seek(false, true);
- }
- return 0;
-}
-
-float CAMLPlayer::GetActualFPS()
-{
- float video_fps = m_video_fps_numerator / m_video_fps_denominator;
- CLog::Log(LOGDEBUG, "CAMLPlayer::GetActualFPS:m_video_fps(%f)", video_fps);
- return video_fps;
-}
-
-void CAMLPlayer::SeekTime(int64_t seek_ms)
-{
- CSingleLock lock(m_aml_csection);
-
- // we cannot seek if paused
- if (m_paused)
- return;
-
- if (seek_ms <= 0)
- seek_ms = 100;
-
- // seek here
- if (m_dll->check_pid_valid(m_pid))
- {
- if (!CheckPlaying())
- return;
- // player_timesearch is seconds (float).
- m_dll->player_timesearch(m_pid, (float)seek_ms/1000.0);
- WaitForSearchOK(5000);
- WaitForPlaying(5000);
- }
-}
-
-int64_t CAMLPlayer::GetTime()
-{
- return m_elapsed_ms;
-}
-
-int64_t CAMLPlayer::GetTotalTime()
-{
- return m_duration_ms;
-}
-
-void CAMLPlayer::GetAudioStreamInfo(int index, SPlayerAudioStreamInfo &info)
-{
- CSingleLock lock(m_aml_csection);
- if (index < 0 || m_audio_streams.empty() || index > (int)(m_audio_streams.size() - 1))
- return;
-
- info.bitrate = m_audio_streams[index]->bit_rate;
-
- info.language = m_audio_streams[index]->language;
-
- info.channels = m_audio_streams[index]->channel;
-
- info.audioCodecName = AudioCodecName(m_audio_streams[index]->format);
-
- if (info.audioCodecName.size())
- info.name = info.audioCodecName + " ";
-
- switch(info.channels)
- {
- case 1:
- info.name += "Mono";
- break;
- case 2:
- info.name += "Stereo";
- break;
- case 6:
- info.name += "5.1";
- break;
- case 7:
- info.name += "6.1";
- break;
- case 8:
- info.name += "7.1";
- break;
- default:
- char temp[32];
- sprintf(temp, "%d-chs", info.channels);
- info.name += temp;
- }
-}
-
-void CAMLPlayer::GetVideoStreamInfo(SPlayerVideoStreamInfo &info)
-{
- CSingleLock lock(m_aml_csection);
- if (m_video_streams.empty() || m_video_index > (int)(m_video_streams.size() - 1))
- return;
-
- info.bitrate = m_video_streams[m_video_index]->bit_rate;
- info.videoCodecName = VideoCodecName(m_video_streams[m_video_index]->format);
- info.videoAspectRatio = g_renderManager.GetAspectRatio();
- g_renderManager.GetVideoRect(info.SrcRect, info.DestRect);
-}
-
-int CAMLPlayer::GetSourceBitrate()
-{
- CLog::Log(LOGDEBUG, "CAMLPlayer::GetSourceBitrate");
- return 0;
-}
-
-int CAMLPlayer::GetBitsPerSample()
-{
- CLog::Log(LOGDEBUG, "CAMLPlayer::GetBitsPerSample");
- return 0;
-}
-
-int CAMLPlayer::GetSampleRate()
-{
- CSingleLock lock(m_aml_csection);
- if (m_audio_streams.empty() || m_audio_index > (int)(m_audio_streams.size() - 1))
- return 0;
-
- return m_audio_streams[m_audio_index]->sample_rate;
-}
-
-int CAMLPlayer::GetPictureWidth()
-{
- //CLog::Log(LOGDEBUG, "CAMLPlayer::GetPictureWidth(%d)", m_video_width);
- return m_video_width;
-}
-
-int CAMLPlayer::GetPictureHeight()
-{
- //CLog::Log(LOGDEBUG, "CAMLPlayer::GetPictureHeight(%)", m_video_height);
- return m_video_height;
-}
-
-bool CAMLPlayer::GetStreamDetails(CStreamDetails &details)
-{
- //CLog::Log(LOGDEBUG, "CAMLPlayer::GetStreamDetails");
- return false;
-}
-
-void CAMLPlayer::ToFFRW(int iSpeed)
-{
- CLog::Log(LOGDEBUG, "CAMLPlayer::ToFFRW: iSpeed(%d), m_speed(%d)", iSpeed, m_speed);
- CSingleLock lock(m_aml_csection);
-
- if (!m_dll->check_pid_valid(m_pid) && m_bAbortRequest)
- return;
-
- if (m_speed != iSpeed)
- {
- // recover power of two value
- int ipower = 0;
- int ispeed = abs(iSpeed);
- while (ispeed >>= 1) ipower++;
-
- switch(ipower)
- {
- // regular playback
- case 0:
- m_dll->player_forward(m_pid, 0);
- break;
- default:
- // N x fast forward/rewind (I-frames)
- // speed playback 1,2,4,8
- if (iSpeed > 0)
- m_dll->player_forward(m_pid, iSpeed);
- else
- m_dll->player_backward(m_pid, -iSpeed);
- break;
- }
-
- m_speed = iSpeed;
- }
-}
-
-bool CAMLPlayer::GetCurrentSubtitle(CStdString& strSubtitle)
-{
- strSubtitle = "";
-
- if (m_subtitle_count)
- {
- // force updated to m_elapsed_ms.
- GetStatus();
- if (m_subtitle_streams[m_subtitle_index]->source == STREAM_SOURCE_NONE && m_subtitle_thread)
- {
- m_subtitle_thread->UpdateSubtitle(strSubtitle, m_elapsed_ms - m_subtitle_delay);
- }
- else
- {
- double pts = DVD_MSEC_TO_TIME(m_elapsed_ms) - DVD_MSEC_TO_TIME(m_subtitle_delay);
- m_dvdOverlayContainer->CleanUp(pts);
- m_dvdPlayerSubtitle->GetCurrentSubtitle(strSubtitle, pts);
- }
- }
-
- return !strSubtitle.IsEmpty();
-}
-
-void CAMLPlayer::OnStartup()
-{
- //m_CurrentVideo.Clear();
- //m_CurrentAudio.Clear();
- //m_CurrentSubtitle.Clear();
-
- //CThread::SetName("AMLPlayer");
-}
-
-void CAMLPlayer::OnExit()
-{
- //CLog::Log(LOGNOTICE, "CAMLPlayer::OnExit()");
-
- m_bStop = true;
- // if we didn't stop playing, advance to the next item in xbmc's playlist
- if (m_options.identify == false)
- {
- if (m_bAbortRequest)
- m_callback.OnPlayBackStopped();
- else
- m_callback.OnPlayBackEnded();
- }
- // set event to inform openfile something went wrong
- // in case openfile is still waiting for this event
- m_ready.Set();
-}
-
-void CAMLPlayer::Process()
-{
- CLog::Log(LOGNOTICE, "CAMLPlayer::Process");
- try
- {
- static AML_URLProtocol vfs_protocol = {
- "vfs",
- CFileURLProtocol::Open,
- CFileURLProtocol::Read,
- CFileURLProtocol::Write,
- CFileURLProtocol::Seek,
- CFileURLProtocol::SeekEx,
- CFileURLProtocol::Close,
- };
-
- CStdString url = m_item.GetPath();
- if (url.Left(strlen("smb://")).Equals("smb://"))
- {
- // the name string needs to persist
- static const char *smb_name = "smb";
- vfs_protocol.name = smb_name;
- }
- else if (url.Left(strlen("afp://")).Equals("afp://"))
- {
- // the name string needs to persist
- static const char *afp_name = "afp";
- vfs_protocol.name = afp_name;
- }
- else if (url.Left(strlen("nfs://")).Equals("nfs://"))
- {
- // the name string needs to persist
- static const char *nfs_name = "nfs";
- vfs_protocol.name = nfs_name;
- }
- else if (url.Left(strlen("rar://")).Equals("rar://"))
- {
- // the name string needs to persist
- static const char *rar_name = "rar";
- vfs_protocol.name = rar_name;
- }
- else if (url.Left(strlen("ftp://")).Equals("ftp://"))
- {
- // the name string needs to persist
- static const char *http_name = "xb-ftp";
- vfs_protocol.name = http_name;
- url = "xb-" + url;
- }
- else if (url.Left(strlen("ftps://")).Equals("ftps://"))
- {
- // the name string needs to persist
- static const char *http_name = "xb-ftps";
- vfs_protocol.name = http_name;
- url = "xb-" + url;
- }
- else if (url.Left(strlen("http://")).Equals("http://"))
- {
- // the name string needs to persist
- static const char *http_name = "xb-http";
- vfs_protocol.name = http_name;
- url = "xb-" + url;
- }
- else if (url.Left(strlen("https://")).Equals("https://"))
- {
- // the name string needs to persist
- static const char *http_name = "xb-https";
- vfs_protocol.name = http_name;
- url = "xb-" + url;
- }
- else if (url.Left(strlen("hdhomerun://")).Equals("hdhomerun://"))
- {
- // the name string needs to persist
- static const char *http_name = "xb-hdhomerun";
- vfs_protocol.name = http_name;
- url = "xb-" + url;
- }
- else if (url.Left(strlen("sftp://")).Equals("sftp://"))
- {
- // the name string needs to persist
- static const char *http_name = "xb-sftp";
- vfs_protocol.name = http_name;
- url = "xb-" + url;
- }
- else if (url.Left(strlen("udp://")).Equals("udp://"))
- {
- std::string udp_params;
- // bump up the default udp params for ffmpeg.
- // ffmpeg will strip out 'dummy=10', we only add it
- // to make the logic below with prpending '&' work right.
- // to watch for udp errors, 'cat /proc/net/udp'
- if (url.find("?") == std::string::npos)
- udp_params.append("?dummy=10");
- if (url.find("pkt_size=") == std::string::npos)
- udp_params.append("&pkt_size=5264");
- if (url.find("buffer_size=") == std::string::npos)
- udp_params.append("&buffer_size=5390336");
- // newer ffmpeg uses fifo_size instead of buf_size
- if (url.find("buf_size=") == std::string::npos)
- udp_params.append("&buf_size=5390336");
-
- if (udp_params.size() > 0)
- url.append(udp_params);
- }
- CLog::Log(LOGDEBUG, "CAMLPlayer::Process: URL=%s", url.c_str());
-
- if (m_dll->player_init() != PLAYER_SUCCESS)
- {
- CLog::Log(LOGDEBUG, "player init failed");
- throw "CAMLPlayer::Process:player init failed";
- }
- CLog::Log(LOGDEBUG, "player init......");
- usleep(50 * 1000);
-
- // must be after player_init
- m_dll->av_register_protocol2(&vfs_protocol, sizeof(vfs_protocol));
-
- static play_control_t play_control;
- memset(&play_control, 0, sizeof(play_control_t));
- // if we do not register a callback,
- // then the libamplayer will free run checking status.
- m_dll->player_register_update_callback(&play_control.callback_fn, &UpdatePlayerInfo, 1000);
- // amlplayer owns file_name and will release on exit
- play_control.file_name = (char*)strdup(url.c_str());
- //play_control->nosound = 1; // if disable audio...,must call this api
- play_control.video_index = -1; //MUST
- play_control.audio_index = -1; //MUST
- play_control.sub_index = -1; //MUST
- play_control.hassub = 1;
- if (m_options.starttime > 0) // player start position in seconds as is starttime
- play_control.t_pos = m_options.starttime;
- else
- play_control.t_pos = -1;
- play_control.need_start = 1; // if 0,you can omit player_start_play API.
- // just play video/audio immediately.
- // if 1,then need call "player_start_play" API;
- play_control.displast_frame = 0; // 0:black out when player exit 1:keep last frame when player exit
-
- // tweak player playback buffers for udp
- if (url.Left(strlen("udp://")).Equals("udp://"))
- {
- play_control.auto_buffing_enable = 1;
- play_control.buffing_min = 0.01; // default = 0.01
- play_control.buffing_middle = 0.02; // default = 0.02
- play_control.buffing_max = 0.20; // default = 0.80
- play_control.byteiobufsize = 1024 * 128; // maps to av_open_input_file buffer size (1024 * 32)
- //play_control.loopbufsize =;
- //play_control.enable_rw_on_pause =;
- }
-
- m_aml_state.clear();
- m_aml_state.push_back(0);
- m_pid = m_dll->player_start(&play_control, 0);
- if (m_pid < 0)
- {
- if (m_log_level > 5)
- CLog::Log(LOGDEBUG, "player start failed! error = %d", m_pid);
- throw "CAMLPlayer::Process:player start failed";
- }
-
- // wait for media to open with 30 second timeout.
- if (WaitForFormatValid(30000))
- {
- // start the playback.
- int res = m_dll->player_start_play(m_pid);
- if (res != PLAYER_SUCCESS)
- throw "CAMLPlayer::Process:player_start_play() failed";
- }
- else
- {
- throw "CAMLPlayer::Process:WaitForFormatValid timeout";
- }
-
- // hide the mainvideo layer so we can get stream info
- // and setup/transition to gui video playback
- // without having video playback blended into it.
- if (m_item.IsVideo())
- ShowMainVideo(false);
-
- // wait for playback to start with 20 second timeout
- if (WaitForPlaying(20000))
- {
- m_speed = 1;
- m_callback.OnPlayBackSpeedChanged(m_speed);
-
- // get our initial status.
- GetStatus();
-
- // the default staturation is too high, drop it
- SetVideoSaturation(110);
-
- // drop CGUIDialogBusy dialog and release the hold in OpenFile.
- m_ready.Set();
-
- // we are playing but hidden and all stream fields are valid.
- // check for video in media content
- if (GetVideoStreamCount() > 0)
- {
- SetAVDelay(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay);
-
- // turn on/off subs
- SetSubtitleVisible(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleOn);
- SetSubTitleDelay(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay);
-
- // setup renderer for bypass. This tell renderer to get out of the way as
- // hw decoder will be doing the actual video rendering in a video plane
- // that is under the GUI layer.
- int width = GetPictureWidth();
- int height = GetPictureHeight();
- double fFrameRate = GetActualFPS();
- unsigned int flags = 0;
-
- flags |= CONF_FLAGS_FULLSCREEN;
- CStdString formatstr = "BYPASS";
- CLog::Log(LOGDEBUG,"%s - change configuration. %dx%d. framerate: %4.2f. format: %s",
- __FUNCTION__, width, height, fFrameRate, formatstr.c_str());
- g_renderManager.IsConfigured();
- if (!g_renderManager.Configure(width, height, width, height, fFrameRate, flags, RENDER_FMT_BYPASS, 0, 0))
- {
- CLog::Log(LOGERROR, "%s - failed to configure renderer", __FUNCTION__);
- }
- if (!g_renderManager.IsStarted())
- {
- CLog::Log(LOGERROR, "%s - renderer not started", __FUNCTION__);
- }
-
- g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack);
-
- m_subtitle_thread = new CAMLSubTitleThread(m_dll);
- m_subtitle_thread->Create();
- }
-
- if (m_options.identify == false)
- m_callback.OnPlayBackStarted();
-
- bool stopPlaying = false;
- while (!m_bAbortRequest && !stopPlaying)
- {
- player_status pstatus = (player_status)GetPlayerSerializedState();
- switch(pstatus)
- {
- case PLAYER_INITING:
- case PLAYER_TYPE_REDY:
- case PLAYER_INITOK:
- if (m_log_level > 5)
- CLog::Log(LOGDEBUG, "CAMLPlayer::Process: %s", m_dll->player_status2str(pstatus));
- // player is parsing file, decoder not running
- break;
-
- default:
- case PLAYER_RUNNING:
- GetStatus();
- // playback status, decoder is running
- break;
-
- case PLAYER_START:
- case PLAYER_BUFFERING:
- case PLAYER_PAUSE:
- case PLAYER_SEARCHING:
- case PLAYER_SEARCHOK:
- case PLAYER_FF_END:
- case PLAYER_FB_END:
- case PLAYER_PLAY_NEXT:
- case PLAYER_BUFFER_OK:
- if (m_log_level > 5)
- CLog::Log(LOGDEBUG, "CAMLPlayer::Process: %s", m_dll->player_status2str(pstatus));
- break;
-
- case PLAYER_FOUND_SUB:
- // found a NEW subtitle in stream.
- // TODO: reload m_subtitle_streams
- if (m_log_level > 5)
- CLog::Log(LOGDEBUG, "CAMLPlayer::Process: %s", m_dll->player_status2str(pstatus));
- break;
-
- case PLAYER_PLAYEND:
- GetStatus();
- if (m_log_level > 5)
- CLog::Log(LOGDEBUG, "CAMLPlayer::Process: %s", m_dll->player_status2str(pstatus));
- break;
-
- case PLAYER_ERROR:
- if (m_log_level > 5)
- {
- printf("CAMLPlayer::Process PLAYER_ERROR\n");
- printf("CAMLPlayer::Process: %s\n", m_dll->player_status2str(pstatus));
- }
- m_bAbortRequest = true;
- break;
-
- case PLAYER_STOPED:
- case PLAYER_EXIT:
- if (m_log_level > 5)
- {
- CLog::Log(LOGDEBUG, "CAMLPlayer::Process PLAYER_STOPPED");
- CLog::Log(LOGDEBUG, "CAMLPlayer::Process: %s", m_dll->player_status2str(pstatus));
- }
- stopPlaying = true;
- break;
- }
- if (!stopPlaying)
- usleep(250 * 1000);
- }
- }
- }
- catch(char* error)
- {
- CLog::Log(LOGERROR, "%s", error);
- }
- catch(...)
- {
- CLog::Log(LOGERROR, "CAMLPlayer::Process Exception thrown");
- }
-
- if (m_log_level > 5)
- CLog::Log(LOGDEBUG, "CAMLPlayer::Process stopped");
- if (m_dll->check_pid_valid(m_pid))
- {
- delete m_subtitle_thread;
- m_subtitle_thread = NULL;
- m_dll->player_stop(m_pid);
- m_dll->player_exit(m_pid);
- m_pid = -1;
- }
-
- // we are done, hide the mainvideo layer.
- ShowMainVideo(false);
- m_ready.Set();
-
- ClearStreamInfos();
-
- // reset ac3/dts passthough
- SetAudioPassThrough(AFORMAT_UNKNOWN);
-
- if (m_log_level > 5)
- CLog::Log(LOGDEBUG, "CAMLPlayer::Process exit");
-}
-
-void CAMLPlayer::GetRenderFeatures(std::vector<int> &renderFeatures)
-{
- renderFeatures.push_back(RENDERFEATURE_ZOOM);
- renderFeatures.push_back(RENDERFEATURE_CONTRAST);
- renderFeatures.push_back(RENDERFEATURE_BRIGHTNESS);
- renderFeatures.push_back(RENDERFEATURE_STRETCH);
-}
-
-void CAMLPlayer::GetDeinterlaceMethods(std::vector<int> &deinterlaceMethods)
-{
- deinterlaceMethods.push_back(VS_INTERLACEMETHOD_DEINTERLACE);
-}
-
-void CAMLPlayer::GetDeinterlaceModes(std::vector<int> &deinterlaceModes)
-{
- deinterlaceModes.push_back(VS_DEINTERLACEMODE_AUTO);
-}
-
-void CAMLPlayer::GetScalingMethods(std::vector<int> &scalingMethods)
-{
-}
-
-void CAMLPlayer::GetAudioCapabilities(std::vector<int> &audioCaps)
-{
- audioCaps.push_back(IPC_AUD_SELECT_STREAM);
- audioCaps.push_back(IPC_AUD_SELECT_OUTPUT);
-#if defined(HAS_AMLPLAYER_AUDIO_SETDELAY)
- audioCaps.push_back(IPC_AUD_OFFSET);
-#endif
-}
-
-void CAMLPlayer::GetSubtitleCapabilities(std::vector<int> &subCaps)
-{
- subCaps.push_back(IPC_SUBS_EXTERNAL);
- subCaps.push_back(IPC_SUBS_SELECT);
- subCaps.push_back(IPC_SUBS_OFFSET);
-}
-
-
-////////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////////
-int CAMLPlayer::GetVideoStreamCount()
-{
- //CLog::Log(LOGDEBUG, "CAMLPlayer::GetVideoStreamCount(%d)", m_video_count);
- return m_video_count;
-}
-
-void CAMLPlayer::ShowMainVideo(bool show)
-{
- if (m_show_mainvideo == show)
- return;
-
- aml_set_sysfs_int("/sys/class/video/disable_video", show ? 0:1);
-
- m_show_mainvideo = show;
-}
-
-void CAMLPlayer::SetVideoZoom(float zoom)
-{
- // input zoom range is 0.5 to 2.0 with a default of 1.0.
- // output zoom range is 2 to 300 with default of 100.
- // we limit that to a range of 50 to 200 with default of 100.
- aml_set_sysfs_int("/sys/class/video/zoom", (int)(100 * zoom));
-}
-
-void CAMLPlayer::SetVideoContrast(int contrast)
-{
- // input contrast range is 0 to 100 with default of 50.
- // output contrast range is -255 to 255 with default of 0.
- contrast = (255 * (contrast - 50)) / 50;
- aml_set_sysfs_int("/sys/class/video/contrast", contrast);
-}
-void CAMLPlayer::SetVideoBrightness(int brightness)
-{
- // input brightness range is 0 to 100 with default of 50.
- // output brightness range is -127 to 127 with default of 0.
- brightness = (127 * (brightness - 50)) / 50;
- aml_set_sysfs_int("/sys/class/video/brightness", brightness);
-}
-void CAMLPlayer::SetVideoSaturation(int saturation)
-{
- // output saturation range is -127 to 127 with default of 127.
- aml_set_sysfs_int("/sys/class/video/saturation", saturation);
-}
-
-void CAMLPlayer::SetAudioPassThrough(int format)
-{
- aml_set_audio_passthrough(
- (m_audio_passthrough_ac3 && format == AFORMAT_AC3) ||
- (m_audio_passthrough_dts && format == AFORMAT_DTS));
-}
-
-int CAMLPlayer::GetPlayerSerializedState(void)
-{
- CSingleLock lock(m_aml_state_csection);
-
- int playerstate;
- int dequeue_size = m_aml_state.size();
-
- if (dequeue_size > 0)
- {
- // serialized state is the front element.
- playerstate = m_aml_state.front();
- // pop the front element if there are
- // more present.
- if (dequeue_size > 1)
- m_aml_state.pop_front();
- }
- else
- {
- // if queue is empty (only at startup),
- // pull the player state directly. this should
- // really never happen but we need to cover it.
- playerstate = m_dll->player_get_state(m_pid);
- m_aml_state.push_back(playerstate);
- }
-
- return playerstate;
-}
-
-
-int CAMLPlayer::UpdatePlayerInfo(int pid, player_info_t *info)
-{
- // we get called when status changes or after update time expires.
- // static callback from libamplayer, since it does not pass an opaque,
- // we have to retreve our player class reference the hard way.
- boost::shared_ptr<CAMLPlayer> amlplayer = boost::dynamic_pointer_cast<CAMLPlayer>(g_application.m_pPlayer->GetInternal());
- if (amlplayer)
- {
- CSingleLock lock(amlplayer->m_aml_state_csection);
- if (amlplayer->m_aml_state.back() != info->status)
- {
- //CLog::Log(LOGDEBUG, "update_player_info: %s, old state %s", player_status2str(info->status), player_status2str(info->last_sta));
- amlplayer->m_aml_state.push_back(info->status);
- }
- }
- return 0;
-}
-
-bool CAMLPlayer::CheckPlaying()
-{
- return ((player_status)GetPlayerSerializedState() == PLAYER_RUNNING);
-}
-
-bool CAMLPlayer::WaitForStopped(int timeout_ms)
-{
- while (!m_bAbortRequest && (timeout_ms > 0))
- {
- player_status pstatus = (player_status)GetPlayerSerializedState();
- if (m_log_level > 5)
- CLog::Log(LOGDEBUG, "CAMLPlayer::WaitForStopped: %s", m_dll->player_status2str(pstatus));
- switch(pstatus)
- {
- default:
- usleep(20 * 1000);
- timeout_ms -= 20;
- break;
- case PLAYER_PLAYEND:
- case PLAYER_STOPED:
- case PLAYER_ERROR:
- case PLAYER_EXIT:
- m_bAbortRequest = true;
- return true;
- break;
- }
- }
-
- return false;
-}
-
-bool CAMLPlayer::WaitForSearchOK(int timeout_ms)
-{
- while (!m_bAbortRequest && (timeout_ms > 0))
- {
- player_status pstatus = (player_status)GetPlayerSerializedState();
- if (m_log_level > 5)
- CLog::Log(LOGDEBUG, "CAMLPlayer::WaitForSearchOK: %s", m_dll->player_status2str(pstatus));
- switch(pstatus)
- {
- default:
- usleep(20 * 1000);
- timeout_ms -= 20;
- break;
- case PLAYER_STOPED:
- return false;
- case PLAYER_ERROR:
- case PLAYER_EXIT:
- m_bAbortRequest = true;
- return false;
- break;
- case PLAYER_SEARCHOK:
- return true;
- break;
- }
- }
-
- return false;
-}
-
-bool CAMLPlayer::WaitForPlaying(int timeout_ms)
-{
- while (!m_bAbortRequest && (timeout_ms > 0))
- {
- // anoying that we have to hammer setting audio volume via mute
- // but we have to catch it before any audio comes out.
- // we cannot do this for m1 (playback will bork) so trap it out.
- if (aml_get_cputype() != 1)
- SetMute(m_audio_mute);
-
- player_status pstatus = (player_status)GetPlayerSerializedState();
- if (m_log_level > 5)
- CLog::Log(LOGDEBUG, "CAMLPlayer::WaitForPlaying: %s", m_dll->player_status2str(pstatus));
- switch(pstatus)
- {
- default:
- usleep(20 * 1000);
- timeout_ms -= 20;
- break;
- case PLAYER_ERROR:
- case PLAYER_EXIT:
- m_bAbortRequest = true;
- return false;
- break;
- case PLAYER_RUNNING:
- // restore mute/volume settings
- SetMute(m_audio_mute);
- return true;
- break;
- }
- }
-
- return false;
-}
-
-bool CAMLPlayer::WaitForFormatValid(int timeout_ms)
-{
- while (timeout_ms > 0)
- {
- player_status pstatus = (player_status)GetPlayerSerializedState();
- if (m_log_level > 5)
- CLog::Log(LOGDEBUG, "CAMLPlayer::WaitForFormatValid: %s", m_dll->player_status2str(pstatus));
- switch(pstatus)
- {
- default:
- usleep(20 * 1000);
- timeout_ms -= 20;
- break;
- case PLAYER_ERROR:
- case PLAYER_EXIT:
- m_bAbortRequest = true;
- return false;
- break;
- case PLAYER_INITOK:
-
- ClearStreamInfos();
-
- media_info_t media_info = {{0}};
-#if defined(TARGET_ANDROID)
- // media_info_t might be different so check its size.
- // player_get_media_info will memset to zero the passed
- // structure so alloc more space and preset to a know value
- // so we can compare the size we use to the size the lib uses.
- int msize = sizeof(media_info_t) + 10240;
- media_info_t *test_media_info = (media_info_t*)calloc(msize, 1);
- memset(test_media_info, 0xEF, msize);
-
- int res = m_dll->player_get_media_info(m_pid, test_media_info);
-
- uint8_t *t1 = (uint8_t*)test_media_info;
- for (size_t i = msize-1; i >= 0; i--)
- {
- if (t1[i] != 0xEF)
- {
- if (sizeof(media_info_t) != i+1)
- {
- CLog::Log(LOGERROR, "CAMLPlayer::media_info_t(%d) size changed to %d",
- sizeof(media_info_t), i+1);
- // size is different, we cannot trust it
- free(test_media_info);
- return false;
- }
- break;
- }
- }
- media_info = *test_media_info;
- free(test_media_info);
-#else
- int res = m_dll->player_get_media_info(m_pid, &media_info);
-#endif
- if (res != PLAYER_SUCCESS)
- return false;
-
- if (m_log_level > 5)
- media_info_dump(&media_info);
-
- // video info
- if (media_info.stream_info.has_video && media_info.stream_info.total_video_num > 0)
- {
- for (int i = 0; i < media_info.stream_info.total_video_num &&
- media_info.stream_info.total_video_num < MAX_VIDEO_STREAMS; i++)
- {
- AMLPlayerStreamInfo *info = new AMLPlayerStreamInfo;
- info->Clear();
-
- info->id = media_info.video_info[i]->id;
- info->type = STREAM_VIDEO;
- info->width = media_info.video_info[i]->width;
- info->height = media_info.video_info[i]->height;
- info->aspect_ratio_num= media_info.video_info[i]->aspect_ratio_num;
- info->aspect_ratio_den= media_info.video_info[i]->aspect_ratio_den;
- info->frame_rate_num = media_info.video_info[i]->frame_rate_num;
- info->frame_rate_den = media_info.video_info[i]->frame_rate_den;
- info->bit_rate = media_info.video_info[i]->bit_rate;
- info->duration = media_info.video_info[i]->duartion;
- info->format = media_info.video_info[i]->format;
-
- m_video_streams.push_back(info);
- }
-
- m_video_index = media_info.stream_info.cur_video_index;
- m_video_count = media_info.stream_info.total_video_num;
- if (m_video_index != 0)
- m_video_index = 0;
- m_video_width = media_info.video_info[m_video_index]->width;
- m_video_height= media_info.video_info[m_video_index]->height;
- m_video_fps_numerator = media_info.video_info[m_video_index]->frame_rate_num;
- m_video_fps_denominator = media_info.video_info[m_video_index]->frame_rate_den;
-
- // bail if we do not get a valid width/height
- if (m_video_width == 0 || m_video_height == 0)
- return false;
- }
-
- // audio info
- if (media_info.stream_info.has_audio && media_info.stream_info.total_audio_num > 0)
- {
- for (int i = 0; i < media_info.stream_info.total_audio_num &&
- media_info.stream_info.total_audio_num < MAX_AUDIO_STREAMS; i++)
- {
- AMLPlayerStreamInfo *info = new AMLPlayerStreamInfo;
- info->Clear();
-
- info->id = media_info.audio_info[i]->id;
- info->type = STREAM_AUDIO;
- info->channel = media_info.audio_info[i]->channel;
- info->sample_rate = media_info.audio_info[i]->sample_rate;
- info->bit_rate = media_info.audio_info[i]->bit_rate;
- info->duration = media_info.audio_info[i]->duration;
- info->format = media_info.audio_info[i]->aformat;
-#if defined(HAS_AMLPLAYER_AUDIO_LANG)
- if (media_info.audio_info[i]->audio_language[0] != 0)
- info->language = std::string(media_info.audio_info[i]->audio_language, 3);
-#endif
-
- m_audio_streams.push_back(info);
- }
-
- m_audio_index = media_info.stream_info.cur_audio_index;
- if (m_audio_index != 0)
- m_audio_index = 0;
- m_audio_count = media_info.stream_info.total_audio_num;
- // setup ac3/dts passthough if required
- SetAudioPassThrough(m_audio_streams[m_audio_index]->format);
- }
-
- // subtitle info
- if (media_info.stream_info.has_sub && media_info.stream_info.total_sub_num > 0)
- {
- for (int i = 0; i < media_info.stream_info.total_sub_num && i < MAX_SUB_STREAMS; i++)
- {
- AMLPlayerStreamInfo *info = new AMLPlayerStreamInfo;
- info->Clear();
-
- info->id = media_info.sub_info[i]->id;
- info->type = STREAM_SUBTITLE;
- if (media_info.sub_info[i]->sub_language && media_info.sub_info[i]->sub_language[0] != 0)
- info->language = std::string(media_info.sub_info[i]->sub_language, 3);
- m_subtitle_streams.push_back(info);
- }
- m_subtitle_index = media_info.stream_info.cur_sub_index;
- }
- // find any external subs
- FindSubtitleFiles();
- // setup count and index
- m_subtitle_count = m_subtitle_streams.size();
- if (m_subtitle_count && m_subtitle_index != 0)
- m_subtitle_index = 0;
-
-#if defined(HAS_AMLPLAYER_CHAPTERS)
- // chapter info
- if (media_info.stream_info.total_chapter_num > 0)
- {
- m_chapter_count = media_info.stream_info.total_chapter_num;
- for (int i = 0; i < m_chapter_count && m_chapter_count < MAX_CHAPTERS; i++)
- {
- if (media_info.chapter_info[i] != NULL)
- {
- AMLChapterInfo *info = new AMLChapterInfo;
-
- info->name = media_info.chapter_info[i]->name;
- info->seekto_ms = media_info.chapter_info[i]->seekto_ms;
- m_chapters.push_back(info);
- }
- }
- }
-#endif
-
- return true;
- break;
- }
- }
-
- return false;
-}
-
-void CAMLPlayer::ClearStreamInfos()
-{
- CSingleLock lock(m_aml_csection);
-
- if (!m_audio_streams.empty())
- {
- for (unsigned int i = 0; i < m_audio_streams.size(); i++)
- delete m_audio_streams[i];
- m_audio_streams.clear();
- }
- m_audio_count = 0;
- m_audio_index = -1;
-
- if (!m_video_streams.empty())
- {
- for (unsigned int i = 0; i < m_video_streams.size(); i++)
- delete m_video_streams[i];
- m_video_streams.clear();
- }
- m_video_count = 0;
- m_video_index = -1;
-
- if (!m_subtitle_streams.empty())
- {
- for (unsigned int i = 0; i < m_subtitle_streams.size(); i++)
- delete m_subtitle_streams[i];
- m_subtitle_streams.clear();
- }
- m_subtitle_count = 0;
- m_subtitle_index = -1;
-
- if (!m_chapters.empty())
- {
- for (unsigned int i = 0; i < m_chapters.size(); i++)
- delete m_chapters[i];
- m_chapters.clear();
- }
- m_chapter_count = 0;
-}
-
-bool CAMLPlayer::GetStatus()
-{
- CSingleLock lock(m_aml_csection);
-
- if (!m_dll->check_pid_valid(m_pid))
- return false;
-
- player_info_t player_info;
- int res = m_dll->player_get_play_info(m_pid, &player_info);
- if (res != PLAYER_SUCCESS)
- return false;
-
- m_elapsed_ms = player_info.current_ms;
- m_duration_ms = 1000 * player_info.full_time;
- //CLog::Log(LOGDEBUG, "CAMLPlayer::GetStatus: audio_bufferlevel(%f), video_bufferlevel(%f), bufed_time(%d), bufed_pos(%lld)",
- // player_info.audio_bufferlevel, player_info.video_bufferlevel, player_info.bufed_time, player_info.bufed_pos);
-
- return true;
-}
-
-void CAMLPlayer::FindSubtitleFiles()
-{
- // find any available external subtitles
- std::vector<CStdString> filenames;
- CUtil::ScanForExternalSubtitles(m_item.GetPath(), filenames);
-
- // find any upnp subtitles
- CStdString key("upnp:subtitle:1");
- for(unsigned s = 1; m_item.HasProperty(key); key.Format("upnp:subtitle:%u", ++s))
- filenames.push_back(m_item.GetProperty(key).asString());
-
- for(unsigned int i=0;i<filenames.size();i++)
- {
- // if vobsub subtitle:
- if (URIUtils::HasExtension(filenames[i], ".idx"))
- {
- CStdString strSubFile;
- if ( CUtil::FindVobSubPair( filenames, filenames[i], strSubFile ) )
- AddSubtitleFile(filenames[i], strSubFile);
- }
- else
- {
- if ( !CUtil::IsVobSub(filenames, filenames[i] ) )
- {
- AddSubtitleFile(filenames[i]);
- }
- }
- }
-}
-
-int CAMLPlayer::AddSubtitleFile(const std::string &filename, const std::string &subfilename)
-{
- std::string ext = URIUtils::GetExtension(filename);
- std::string vobsubfile = subfilename;
-
- if(ext == ".idx")
- {
- /* TODO: we do not handle idx/sub binary subs yet.
- if (vobsubfile.empty())
- vobsubfile = URIUtils::ReplaceExtension(filename, ".sub");
-
- CDVDDemuxVobsub v;
- if(!v.Open(filename, vobsubfile))
- return -1;
- m_SelectionStreams.Update(NULL, &v);
- int index = m_SelectionStreams.IndexOf(STREAM_SUBTITLE, m_SelectionStreams.Source(STREAM_SOURCE_DEMUX_SUB, filename), 0);
- m_SelectionStreams.Get(STREAM_SUBTITLE, index).flags = flags;
- m_SelectionStreams.Get(STREAM_SUBTITLE, index).filename2 = vobsubfile;
- return index;
- */
- return -1;
- }
- if(ext == ".sub")
- {
- // check for texual sub, if this is a idx/sub pair, ignore it.
- CStdString strReplace(URIUtils::ReplaceExtension(filename,".idx"));
- if (XFILE::CFile::Exists(strReplace))
- return -1;
- }
-
- AMLPlayerStreamInfo *info = new AMLPlayerStreamInfo;
- info->Clear();
-
- info->id = 0;
- info->type = STREAM_SUBTITLE;
- info->source = STREAM_SOURCE_TEXT;
- info->filename = filename;
- info->name = URIUtils::GetFileName(filename);
- info->frame_rate_num = m_video_fps_numerator;
- info->frame_rate_den = m_video_fps_denominator;
- m_subtitle_streams.push_back(info);
-
- return m_subtitle_streams.size();
-}
-
-bool CAMLPlayer::OpenSubtitleStream(int index)
-{
- CLog::Log(LOGNOTICE, "Opening external subtitle stream: %i", index);
-
- CDemuxStream* pStream = NULL;
- std::string filename;
- CDVDStreamInfo hint;
-
- if (m_subtitle_streams[index]->source == STREAM_SOURCE_DEMUX_SUB)
- {
- /*
- int index = m_SelectionStreams.IndexOf(STREAM_SUBTITLE, source, iStream);
- if(index < 0)
- return false;
- SelectionStream st = m_SelectionStreams.Get(STREAM_SUBTITLE, index);
-
- if(!m_pSubtitleDemuxer || m_pSubtitleDemuxer->GetFileName() != st.filename)
- {
- CLog::Log(LOGNOTICE, "Opening Subtitle file: %s", st.filename.c_str());
- auto_ptr<CDVDDemuxVobsub> demux(new CDVDDemuxVobsub());
- if(!demux->Open(st.filename, st.filename2))
- return false;
- m_pSubtitleDemuxer = demux.release();
- }
-
- pStream = m_pSubtitleDemuxer->GetStream(iStream);
- if(!pStream || pStream->disabled)
- return false;
- pStream->SetDiscard(AVDISCARD_NONE);
- double pts = m_dvdPlayerVideo.GetCurrentPts();
- if(pts == DVD_NOPTS_VALUE)
- pts = m_CurrentVideo.dts;
- if(pts == DVD_NOPTS_VALUE)
- pts = 0;
- pts += m_offset_pts;
- m_pSubtitleDemuxer->SeekTime((int)(1000.0 * pts / (double)DVD_TIME_BASE));
-
- hint.Assign(*pStream, true);
- */
- return false;
- }
- else if (m_subtitle_streams[index]->source == STREAM_SOURCE_TEXT)
- {
- filename = m_subtitle_streams[index]->filename;
-
- hint.Clear();
- hint.fpsscale = m_subtitle_streams[index]->frame_rate_den;
- hint.fpsrate = m_subtitle_streams[index]->frame_rate_num;
- }
-
- m_dvdPlayerSubtitle->CloseStream(true);
- if (!m_dvdPlayerSubtitle->OpenStream(hint, filename))
- {
- CLog::Log(LOGWARNING, "%s - Unsupported stream %d. Stream disabled.", __FUNCTION__, index);
- if(pStream)
- {
- pStream->disabled = true;
- pStream->SetDiscard(AVDISCARD_ALL);
- }
- return false;
- }
-
- return true;
-}
-
-void CAMLPlayer::SetVideoRect(const CRect &SrcRect, const CRect &DestRect)
-{
- // this routine gets called every video frame
- // and is in the context of the renderer thread so
- // do not do anything stupid here.
-
- // video zoom adjustment.
- float zoom = CMediaSettings::Get().GetCurrentVideoSettings().m_CustomZoomAmount;
- if ((int)(zoom * 1000) != (int)(m_zoom * 1000))
- {
- m_zoom = zoom;
- }
- // video contrast adjustment.
- int contrast = CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast;
- if (contrast != m_contrast)
- {
- SetVideoContrast(contrast);
- m_contrast = contrast;
- }
- // video brightness adjustment.
- int brightness = CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness;
- if (brightness != m_brightness)
- {
- SetVideoBrightness(brightness);
- m_brightness = brightness;
- }
-
- // check if destination rect or video view mode has changed
- if ((m_dst_rect != DestRect) || (m_view_mode != CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode))
- {
- m_dst_rect = DestRect;
- m_view_mode = CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode;
- }
- else
- {
- // mainvideo 'should' be showing already if we get here, make sure.
- ShowMainVideo(true);
- return;
- }
-
- CRect gui, display, dst_rect;
- gui = g_graphicsContext.GetViewWindow();
- // when display is at 1080p, we have freescale enabled
- // and that scales all layers into 1080p display including video,
- // so we have to setup video axis for 720p instead of 1080p... Boooo.
- display = g_graphicsContext.GetViewWindow();
- //RESOLUTION res = g_graphicsContext.GetVideoResolution();
- //display.SetRect(0, 0, CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth, CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight);
- dst_rect = m_dst_rect;
- if (gui != display)
- {
- float xscale = display.Width() / gui.Width();
- float yscale = display.Height() / gui.Height();
- dst_rect.x1 *= xscale;
- dst_rect.x2 *= xscale;
- dst_rect.y1 *= yscale;
- dst_rect.y2 *= yscale;
- }
-
- ShowMainVideo(false);
-
- // goofy 0/1 based difference in aml axis coordinates.
- // fix them.
- dst_rect.x2--;
- dst_rect.y2--;
-
- char video_axis[256] = {0};
- sprintf(video_axis, "%d %d %d %d", (int)dst_rect.x1, (int)dst_rect.y1, (int)dst_rect.x2, (int)dst_rect.y2);
- aml_set_sysfs_str("/sys/class/video/axis", video_axis);
- // make sure we are in 'full stretch' so we can stretch
- aml_set_sysfs_int("/sys/class/video/screen_mode", 1);
-/*
- CStdString rectangle;
- rectangle.Format("%i,%i,%i,%i",
- (int)dst_rect.x1, (int)dst_rect.y1,
- (int)dst_rect.Width(), (int)dst_rect.Height());
- CLog::Log(LOGDEBUG, "CAMLPlayer::SetVideoRect:dst_rect(%s)", rectangle.c_str());
-*/
- // we only get called once gui has changed to something
- // that would show video playback, so show it.
- ShowMainVideo(true);
-}
-
-void CAMLPlayer::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect)
-{
- CAMLPlayer *player = (CAMLPlayer*)ctx;
- player->SetVideoRect(SrcRect, DestRect);
-}
-