1 /*
2 * This file is part of Wireless Display Software for Linux OS
3 *
4 * Copyright (C) 2014 Intel Corporation.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 */
21
22 #include "libwds/rtsp/videoformats.h"
23
24 #include <cassert>
25
26 #include "libwds/rtsp/macros.h"
27
28 namespace wds {
29 namespace rtsp {
30
31 namespace {
32 template <typename EnumType>
EnumListToMask(const std::vector<EnumType> & from)33 unsigned int EnumListToMask(const std::vector<EnumType>& from) {
34 unsigned int result = 0;
35
36 for (auto item : from) {
37 result = result | (1 << item);
38 }
39
40 return result;
41 }
42 } //namespace
43
44 using wds::H264VideoFormat;
45 using wds::H264VideoCodec;
46
H264Codec(unsigned char profile,unsigned char level,unsigned int cea_support,unsigned int vesa_support,unsigned int hh_support,unsigned char latency,unsigned short min_slice_size,unsigned short slice_enc_params,unsigned char frame_rate_control_support,unsigned short max_hres,unsigned short max_vres)47 H264Codec::H264Codec(unsigned char profile, unsigned char level,
48 unsigned int cea_support, unsigned int vesa_support,
49 unsigned int hh_support, unsigned char latency,
50 unsigned short min_slice_size, unsigned short slice_enc_params,
51 unsigned char frame_rate_control_support,
52 unsigned short max_hres, unsigned short max_vres)
53 : profile(profile),
54 level(level),
55 cea_support(cea_support),
56 vesa_support(vesa_support),
57 hh_support(hh_support),
58 latency(latency),
59 min_slice_size(min_slice_size),
60 slice_enc_params(slice_enc_params),
61 frame_rate_control_support(frame_rate_control_support),
62 max_hres(max_hres),
63 max_vres(max_vres) {}
64
H264Codec(const H264VideoFormat & format)65 H264Codec::H264Codec(const H264VideoFormat& format)
66 : profile(1 << format.profile),
67 level(1 << format.level),
68 cea_support((format.type == CEA) ? 1 << format.rate_resolution : 0),
69 vesa_support((format.type == VESA) ? 1 << format.rate_resolution : 0),
70 hh_support((format.type == HH) ? 1 << format.rate_resolution : 0),
71 latency(0),
72 min_slice_size(0),
73 slice_enc_params(0),
74 frame_rate_control_support(0),
75 max_hres(0),
76 max_vres(0) {
77
78 }
79
H264Codec(const H264VideoCodec & format)80 H264Codec::H264Codec(const H264VideoCodec& format)
81 : profile(1 << format.profile),
82 level(1 << format.level),
83 cea_support(format.cea_rr.to_ulong()),
84 vesa_support(format.vesa_rr.to_ulong()),
85 hh_support(format.hh_rr.to_ulong()),
86 latency(0),
87 min_slice_size(0),
88 slice_enc_params(0),
89 frame_rate_control_support(0),
90 max_hres(0),
91 max_vres(0) {
92
93 }
94
95
ToString() const96 std::string H264Codec::ToString() const {
97 std::string ret;
98 MAKE_HEX_STRING_2(profile_str, profile);
99 MAKE_HEX_STRING_2(level_str, level);
100 MAKE_HEX_STRING_8(cea_support_str, cea_support);
101 MAKE_HEX_STRING_8(vesa_support_str, vesa_support);
102 MAKE_HEX_STRING_8(hh_support_str, hh_support);
103 MAKE_HEX_STRING_2(latency_str, latency);
104 MAKE_HEX_STRING_4(min_slice_size_str, min_slice_size);
105 MAKE_HEX_STRING_4(slice_enc_params_str, slice_enc_params);
106 MAKE_HEX_STRING_2(frame_rate_control_support_str, frame_rate_control_support);
107
108 ret = profile_str + std::string(SPACE)
109 + level_str + std::string(SPACE)
110 + cea_support_str + std::string(SPACE)
111 + vesa_support_str + std::string(SPACE)
112 + hh_support_str + std::string(SPACE)
113 + latency_str + std::string(SPACE)
114 + min_slice_size_str + std::string(SPACE)
115 + slice_enc_params_str + std::string(SPACE)
116 + frame_rate_control_support_str + std::string(SPACE);
117
118 if (max_hres > 0) {
119 MAKE_HEX_STRING_4(max_hres_str, max_hres);
120 ret += max_hres_str;
121 } else {
122 ret += NONE;
123 }
124 ret += std::string(SPACE);
125
126 if (max_vres > 0) {
127 MAKE_HEX_STRING_4(max_vres_str, max_vres);
128 ret += max_vres_str;
129 } else {
130 ret += NONE;
131 }
132
133 return ret;
134 }
135
136 namespace {
137
138 template <typename EnumType, typename ArgType>
139 EnumType MaskToEnum(ArgType from, EnumType biggest_value) {
140 assert(from != 0);
141 ArgType copy = from;
142 unsigned result = 0;
143 while ((copy & 1) == 0 && copy != 0) {
144 copy = copy >> 1;
145 ++result;
146 }
147 if (result > static_cast<unsigned>(biggest_value)) {
148 assert(false);
149 return biggest_value;
150 }
151 return static_cast<EnumType>(result);
152 }
153
154 template <typename EnumType, typename ArgType>
MaskToEnumList(ArgType from,EnumType biggest_value)155 std::vector<EnumType> MaskToEnumList(ArgType from, EnumType biggest_value) {
156 assert(from != 0);
157 ArgType copy = from;
158 unsigned enum_value = 0;
159 std::vector<EnumType> result;
160
161 while (copy != 0) {
162 if ((copy & 1) != 0) {
163 if (enum_value > static_cast<unsigned>(biggest_value))
164 break;
165
166 result.push_back(static_cast<EnumType>(enum_value));
167 }
168 copy = copy >> 1;
169 ++enum_value;
170 }
171
172 return result;
173 }
174
ToH264Profile(unsigned char profile)175 inline H264Profile ToH264Profile(unsigned char profile) {
176 return MaskToEnum<H264Profile>(profile, CHP);
177 }
178
ToH264Level(unsigned char level)179 inline H264Level ToH264Level(unsigned char level) {
180 return MaskToEnum<H264Level>(level, k4_2);
181 }
182
183 } // namespace
184
ToH264VideoCodec() const185 H264VideoCodec H264Codec::ToH264VideoCodec() const {
186 H264VideoCodec result;
187 result.profile = ToH264Profile(profile);
188 result.level = ToH264Level(level);
189 result.cea_rr = RateAndResolutionsBitmap(cea_support);
190 result.vesa_rr = RateAndResolutionsBitmap(vesa_support);
191 result.hh_rr = RateAndResolutionsBitmap(hh_support);
192 return result;
193 }
194
VideoFormats()195 VideoFormats::VideoFormats() : Property(VideoFormatsPropertyType, true) {
196 }
197
VideoFormats(NativeVideoFormat format,bool preferred_display_mode,const std::vector<H264VideoFormat> & h264_formats)198 VideoFormats::VideoFormats(NativeVideoFormat format,
199 bool preferred_display_mode,
200 const std::vector<H264VideoFormat>& h264_formats)
201 : Property(VideoFormatsPropertyType),
202 preferred_display_mode_(preferred_display_mode ? 1 : 0) {
203 native_ = (format.rate_resolution << 3) | format.type;
204 for(auto h264_format : h264_formats)
205 h264_codecs_.push_back(H264Codec(h264_format));
206 }
207
VideoFormats(NativeVideoFormat format,bool preferred_display_mode,const std::vector<H264VideoCodec> & h264_formats)208 VideoFormats::VideoFormats(NativeVideoFormat format,
209 bool preferred_display_mode,
210 const std::vector<H264VideoCodec>& h264_formats)
211 : Property(VideoFormatsPropertyType),
212 preferred_display_mode_(preferred_display_mode ? 1 : 0) {
213 native_ = (format.rate_resolution << 3) | format.type;
214 for(auto h264_format : h264_formats)
215 h264_codecs_.push_back(H264Codec(h264_format));
216 }
217
VideoFormats(unsigned char native,unsigned char preferred_display_mode,const H264Codecs & h264_codecs)218 VideoFormats::VideoFormats(unsigned char native,
219 unsigned char preferred_display_mode,
220 const H264Codecs& h264_codecs)
221 : Property(VideoFormatsPropertyType),
222 native_(native),
223 preferred_display_mode_(preferred_display_mode),
224 h264_codecs_(h264_codecs) {
225 }
226
~VideoFormats()227 VideoFormats::~VideoFormats() {
228 }
229
230 namespace {
231
232 template <typename EnumType>
GetFormatFromIndex(unsigned index,EnumType biggest_value)233 NativeVideoFormat GetFormatFromIndex(unsigned index, EnumType biggest_value) {
234 if (index <= static_cast<unsigned>(biggest_value))
235 return NativeVideoFormat(static_cast<EnumType>(index));
236 assert(false);
237 return NativeVideoFormat(biggest_value);
238 }
239
240 }
241
GetNativeFormat() const242 NativeVideoFormat VideoFormats::GetNativeFormat() const {
243 unsigned index = native_ >> 3;
244 unsigned selection_bits = native_ & 7;
245 switch (selection_bits) {
246 case 0: // 0b000 CEA
247 return GetFormatFromIndex<CEARatesAndResolutions>(index, CEA1920x1080p24);
248 case 1: // 0b001 VESA
249 return GetFormatFromIndex<VESARatesAndResolutions>(index, VESA1920x1200p30);
250 case 2: // 0b010 HH
251 return GetFormatFromIndex<HHRatesAndResolutions>(index, HH848x480p60);
252 default:
253 assert(false);
254 break;
255 }
256 return NativeVideoFormat(CEA640x480p60);
257 }
258
GetH264Formats() const259 std::vector<H264VideoFormat> VideoFormats::GetH264Formats() const {
260 std::vector<H264VideoFormat> result;
261 for (const auto& codec : h264_codecs_)
262 PopulateVideoFormatList(codec.ToH264VideoCodec(), result);
263 return result;
264 }
265
GetH264VideoCodecs() const266 std::vector<H264VideoCodec> VideoFormats::GetH264VideoCodecs() const {
267 std::vector<H264VideoCodec> result;
268 for (const auto& codec : h264_codecs_)
269 result.push_back(codec.ToH264VideoCodec());
270 return result;
271 }
272
ToString() const273 std::string VideoFormats::ToString() const {
274 std::string ret;
275
276 ret = PropertyName::wfd_video_formats
277 + std::string(SEMICOLON)+ std::string(SPACE);
278
279 if (is_none())
280 return ret + NONE;
281
282 MAKE_HEX_STRING_2(native, native_);
283 MAKE_HEX_STRING_2(preferred_display_mode, preferred_display_mode_);
284
285 ret += native + std::string(SPACE)
286 + preferred_display_mode + std::string(SPACE);
287
288 auto it = h264_codecs_.begin();
289 auto end = h264_codecs_.end();
290 while(it != end) {
291 ret += (*it).ToString();
292 ++it;
293 if (it != end)
294 ret += ", ";
295 }
296
297 return ret;
298 }
299
300 } // namespace rtsp
301 } // namespace wds
302