File indexing completed on 2025-02-23 04:35:13
0001 // SPDX-FileCopyrightText: 2021 Linus Jahn <lnj@kaidan.im> 0002 // SPDX-License-Identifier: GPL-3.0-or-later 0003 0004 #include "mediaformat.h" 0005 0006 #include <QJsonObject> 0007 0008 using namespace QInvidious; 0009 0010 MediaFormatBase::Container containerFromString(QStringView container) 0011 { 0012 if (container == u"webm") { 0013 return MediaFormatBase::WebM; 0014 } 0015 if (container == u"mp4") { 0016 return MediaFormatBase::Mp4; 0017 } 0018 if (container == u"m4a") { 0019 return MediaFormatBase::M4a; 0020 } 0021 return MediaFormatBase::InvalidContainer; 0022 } 0023 0024 MediaFormatBase::Codec codecFromString(QStringView codec) 0025 { 0026 if (codec == u"opus") { 0027 return MediaFormatBase::Opus; 0028 } 0029 if (codec == u"aac" || codec.startsWith(u"mp4a")) { 0030 return MediaFormatBase::AAC; 0031 } 0032 if (codec == u"vp9") { 0033 return MediaFormatBase::VP9; 0034 } 0035 if (codec == u"h264" || codec.startsWith(u"avc1")) { 0036 return MediaFormatBase::H264; 0037 } 0038 if (codec.startsWith(u"av01")) { 0039 return MediaFormatBase::AV1; 0040 } 0041 return MediaFormatBase::InvalidCodec; 0042 } 0043 0044 MediaFormatBase MediaFormatBase::fromJson(const QJsonObject &obj, MediaFormatBase &format) 0045 { 0046 format.m_url = QUrl(obj.value(u"url").toString()); 0047 format.m_formatId = obj.value(u"itag").toInt(); 0048 format.m_fps = obj.value(u"fps").toInt(); 0049 // remove 'p' from "2160p", resolution doesn't contain something like "720p60" 0050 if (const auto resolution = obj.value(u"resolution").toString(); resolution.size() > 1) { 0051 format.m_resolution = resolution.chopped(1).toUInt(); 0052 } 0053 format.m_container = containerFromString(obj.value(u"container").toString()); 0054 return format; 0055 } 0056 0057 QUrl MediaFormatBase::url() const 0058 { 0059 return m_url; 0060 } 0061 0062 uint16_t MediaFormatBase::formatId() const 0063 { 0064 return m_formatId; 0065 } 0066 0067 uint8_t MediaFormatBase::fps() const 0068 { 0069 return m_fps; 0070 } 0071 0072 uint16_t MediaFormatBase::resolution() const 0073 { 0074 return m_resolution; 0075 } 0076 0077 auto MediaFormatBase::container() const -> Container 0078 { 0079 return m_container; 0080 } 0081 0082 MediaFormat MediaFormat::fromJson(const QJsonObject &obj, MediaFormat &format) 0083 { 0084 MediaFormatBase::fromJson(obj, format); 0085 format.m_bitrate = obj.value(u"bitrate").toInt(); 0086 format.m_size = obj.value(u"clen").toInt(); 0087 format.m_codec = codecFromString(obj.value(u"encoding").toString()); 0088 // the value is provided as a string and in nanoseconds 0089 format.m_createdTimestamp = QDateTime::fromMSecsSinceEpoch(QStringView(obj.value(u"lmt").toString()).toULongLong() / 1000); 0090 return format; 0091 } 0092 0093 MediaFormat::MediaType MediaFormat::mediaType() const 0094 { 0095 switch (m_codec) { 0096 case Opus: 0097 case AAC: 0098 return Audio; 0099 case VP9: 0100 case H264: 0101 case AV1: 0102 return Video; 0103 case InvalidCodec: 0104 break; 0105 } 0106 return Unknown; 0107 } 0108 0109 uint32_t MediaFormat::bitrate() const 0110 { 0111 return m_bitrate; 0112 } 0113 0114 void MediaFormat::setBitrate(uint32_t bitrate) 0115 { 0116 m_bitrate = bitrate; 0117 } 0118 0119 uint64_t MediaFormat::size() const 0120 { 0121 return m_size; 0122 } 0123 0124 void MediaFormat::setSize(uint64_t size) 0125 { 0126 m_size = size; 0127 } 0128 0129 auto MediaFormat::codec() const -> Codec 0130 { 0131 return m_codec; 0132 } 0133 0134 void MediaFormat::setCodec(Codec codec) 0135 { 0136 m_codec = codec; 0137 } 0138 0139 QDateTime MediaFormat::createdTimestamp() const 0140 { 0141 return m_createdTimestamp; 0142 } 0143 0144 void MediaFormat::setCreatedTimestamp(const QDateTime &createdTimestamp) 0145 { 0146 m_createdTimestamp = createdTimestamp; 0147 } 0148 0149 MediaFormatCombined MediaFormatCombined::fromJson(const QJsonObject &obj, MediaFormatCombined &format) 0150 { 0151 MediaFormatBase::fromJson(obj, format); 0152 // something like: "video/mp4; codecs=\"avc1.42001E, mp4a.40.2\"" 0153 const auto codecsStr = obj.value(u"format").toString(); 0154 const QStringView codecs = codecsStr; 0155 const auto codecsStart = codecs.indexOf(u'"'); 0156 const auto codecsLength = codecsStart - codecs.indexOf(u'"', codecsStart); 0157 const auto codecList = codecs.mid(codecsStart, codecsLength).split(u", "); 0158 if (codecList.size() >= 1) { 0159 format.m_videoCodec = codecFromString(codecList[0]); 0160 if (codecList.size() >= 2) { 0161 format.m_audioCodec = codecFromString(codecList[1]); 0162 } 0163 } 0164 return format; 0165 } 0166 0167 auto MediaFormatCombined::audioCodec() const -> Codec 0168 { 0169 return m_audioCodec; 0170 } 0171 0172 void MediaFormatCombined::setAudioCodec(Codec audioCodec) 0173 { 0174 m_audioCodec = audioCodec; 0175 } 0176 0177 auto MediaFormatCombined::videoCodec() const -> Codec 0178 { 0179 return m_videoCodec; 0180 } 0181 0182 void MediaFormatCombined::setVideoCodec(Codec videoCodec) 0183 { 0184 m_videoCodec = videoCodec; 0185 }