File indexing completed on 2024-06-16 04:38:30
0001 /* 0002 SPDX-FileCopyrightText: 2003 Fabrice Bellard 0003 SPDX-FileCopyrightText: 2020-2022 Mladen Milinkovic <max@smoothware.net> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "videostate.h" 0009 0010 #include <KLocalizedString> 0011 #include "helpers/languagecode.h" 0012 #include "videoplayer/backend/ffplayer.h" 0013 0014 using namespace SubtitleComposer; 0015 0016 VideoState::VideoState() 0017 : audDec(this), 0018 #ifdef AUDIO_VISUALIZATION 0019 sample_array(8 * 65536), 0020 #endif 0021 vidDec(this) 0022 { 0023 } 0024 0025 int 0026 VideoState::masterSyncType() { 0027 if(av_sync_type == AV_SYNC_VIDEO_MASTER) 0028 return vidStream ? AV_SYNC_VIDEO_MASTER : AV_SYNC_AUDIO_MASTER; 0029 if(av_sync_type == AV_SYNC_AUDIO_MASTER) 0030 return audStream ? AV_SYNC_AUDIO_MASTER : AV_SYNC_EXTERNAL_CLOCK; 0031 return AV_SYNC_EXTERNAL_CLOCK; 0032 } 0033 0034 Clock * 0035 VideoState::masterClock() 0036 { 0037 switch(masterSyncType()) { 0038 case AV_SYNC_VIDEO_MASTER: return &vidClk; 0039 case AV_SYNC_AUDIO_MASTER: return &audClk; 0040 default: return &extClk; 0041 } 0042 } 0043 0044 0045 double 0046 VideoState::masterTime() 0047 { 0048 switch(masterSyncType()) { 0049 case AV_SYNC_VIDEO_MASTER: return vidClk.get(); 0050 case AV_SYNC_AUDIO_MASTER: return audClk.get(); 0051 default: return extClk.get(); 0052 } 0053 } 0054 0055 void 0056 VideoState::checkExternalClockSpeed() 0057 { 0058 if((vidStreamIdx >= 0 && vidPQ.nbPackets() <= EXTERNAL_CLOCK_MIN_FRAMES) || (audStreamIdx >= 0 && audPQ.nbPackets() <= EXTERNAL_CLOCK_MIN_FRAMES)) { 0059 extClk.setSpeed(FFMAX(EXTERNAL_CLOCK_SPEED_MIN, extClk.speed() - EXTERNAL_CLOCK_SPEED_STEP)); 0060 } else if((vidStreamIdx < 0 || vidPQ.nbPackets() > EXTERNAL_CLOCK_MAX_FRAMES) && (audStreamIdx < 0 || audPQ.nbPackets() > EXTERNAL_CLOCK_MAX_FRAMES)) { 0061 extClk.setSpeed(FFMIN(EXTERNAL_CLOCK_SPEED_MAX, extClk.speed() + EXTERNAL_CLOCK_SPEED_STEP)); 0062 } else { 0063 const double speed = extClk.speed(); 0064 if(speed != 1.0) 0065 extClk.setSpeed(speed + EXTERNAL_CLOCK_SPEED_STEP * (1.0 - speed) / fabs(1.0 - speed)); 0066 } 0067 } 0068 0069 void 0070 VideoState::notifyState() 0071 { 0072 if(abortRequested) 0073 emit player->stateChanged(FFPlayer::Stopped); 0074 else if(paused || step) 0075 emit player->stateChanged(FFPlayer::Paused); 0076 else 0077 emit player->stateChanged(FFPlayer::Playing); 0078 } 0079 0080 void 0081 VideoState::notifySpeed() 0082 { 0083 const double speed = audDec.pitch(); 0084 masterClock()->setSpeed(speed); 0085 emit player->speedChanged(speed); 0086 } 0087 0088 void 0089 VideoState::notifyLoaded() 0090 { 0091 emit player->mediaLoaded(); 0092 0093 const AVStream *st = audStream ? audStream : vidStream; 0094 const double streamDuration = double(st->duration) * st->time_base.num / st->time_base.den; 0095 const double containerDuration = double(fmtContext->duration) / AV_TIME_BASE; 0096 emit player->durationChanged(qMax(streamDuration, containerDuration)); 0097 0098 notifySpeed(); 0099 emit player->volumeChanged(player->volume()); 0100 emit player->muteChanged(player->muted()); 0101 0102 QStringList audioStreams, videoStreams, subtitleStreams; 0103 const AVCodecDescriptor *desc; 0104 for(unsigned int i = 0; i < fmtContext->nb_streams; i++) { 0105 AVStream *stream = fmtContext->streams[i]; 0106 QString *streamName; 0107 0108 switch(stream->codecpar->codec_type) { 0109 case AVMEDIA_TYPE_VIDEO: 0110 videoStreams.append(i18n("Video Stream #%1", videoStreams.size() + 1)); 0111 streamName = &videoStreams.last(); 0112 break; 0113 case AVMEDIA_TYPE_AUDIO: 0114 audioStreams.append(i18n("Audio Stream #%1", audioStreams.size() + 1)); 0115 streamName = &audioStreams.last(); 0116 break; 0117 case AVMEDIA_TYPE_SUBTITLE: 0118 desc = avcodec_descriptor_get(stream->codecpar->codec_id); 0119 if(desc && (desc->props & AV_CODEC_PROP_TEXT_SUB)) { 0120 subtitleStreams.append(i18n("Subtitle Stream #%1", subtitleStreams.size() + 1)); 0121 streamName = &subtitleStreams.last(); 0122 } else { 0123 streamName = nullptr; 0124 } 0125 break; 0126 default: 0127 streamName = nullptr; 0128 break; 0129 } 0130 if(!streamName) 0131 continue; 0132 0133 *streamName += QStringLiteral(": "); 0134 AVDictionaryEntry *tag = av_dict_get(stream->metadata, "lang", nullptr, AV_DICT_IGNORE_SUFFIX); 0135 *streamName += tag ? QString("%2 (%3)").arg(LanguageCode::nameFromIso(tag->value)).arg(tag->value) : QStringLiteral("Unknown"); 0136 0137 if((tag = av_dict_get(stream->metadata, "title", nullptr, 0)) != nullptr) 0138 *streamName += QStringLiteral(": ") + QString::fromUtf8(tag->value); 0139 0140 *streamName += QStringLiteral(" [") + QString::fromUtf8(avcodec_descriptor_get(stream->codecpar->codec_id)->name) + QStringLiteral("]"); 0141 // if(stream->codecpar->extradata) 0142 // QByteArray((const char*)stream->codecpar->extradata, stream->codecpar->extradata_size); 0143 } 0144 emit player->videoStreamsChanged(videoStreams); 0145 emit player->audioStreamsChanged(audioStreams); 0146 emit player->subtitleStreamsChanged(subtitleStreams); 0147 0148 notifyState(); 0149 }