1 /*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2015, Anthony Minessale II <anthm@freeswitch.org>
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18 *
19 * The Initial Developer of the Original Code is
20 * Seven Du <dujinfang@gmail.com>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Anthony Minessale II <anthm@freeswitch.org>
27 * Seven Du <dujinfang@gmail.com>
28 * Sam Russell <sam.h.russell@gmail.com>
29 *
30 * mod_vpx.c -- VP8/9 Video Codec, with transcoding
31 *
32 */
33
34 #include <switch.h>
35 #ifdef SWITCH_HAVE_YUV
36 #ifdef SWITCH_HAVE_VPX
37 #include <vpx/vpx_encoder.h>
38 #include <vpx/vpx_decoder.h>
39 #include <vpx/vp8cx.h>
40 #include <vpx/vp8dx.h>
41 #include <vpx/vp8.h>
42
43 // #define DEBUG_VP9
44
45 #ifdef DEBUG_VP9
46 #define VPX_SWITCH_LOG_LEVEL SWITCH_LOG_ERROR
47 #else
48 #define VPX_SWITCH_LOG_LEVEL SWITCH_LOG_DEBUG1
49 #endif
50
51 #define SLICE_SIZE SWITCH_DEFAULT_VIDEO_SIZE
52 #define KEY_FRAME_MIN_FREQ 250000
53
54 #define CODEC_TYPE_ANY 0
55 #define CODEC_TYPE_VP8 8
56 #define CODEC_TYPE_VP9 9
57
58 typedef struct my_vpx_cfg_s {
59 char name[64];
60 int lossless;
61 int cpuused;
62 int token_parts;
63 int static_thresh;
64 int noise_sensitivity;
65 int max_intra_bitrate_pct;
66 vp9e_tune_content tune_content;
67
68 vpx_codec_enc_cfg_t enc_cfg;
69 vpx_codec_dec_cfg_t dec_cfg;
70 switch_event_t *codecs;
71 } my_vpx_cfg_t;
72
73 #define SHOW(cfg, field) switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO, " %-28s = %d\n", #field, cfg->field)
74
show_config(my_vpx_cfg_t * my_cfg,vpx_codec_enc_cfg_t * cfg)75 static void show_config(my_vpx_cfg_t *my_cfg, vpx_codec_enc_cfg_t *cfg)
76 {
77 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " %-28s = %s\n", "name", my_cfg->name);
78 switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO, " %-28s = %d\n", "decoder.threads", my_cfg->dec_cfg.threads);
79
80 SHOW(my_cfg, lossless);
81 SHOW(my_cfg, cpuused);
82 SHOW(my_cfg, token_parts);
83 SHOW(my_cfg, static_thresh);
84 SHOW(my_cfg, noise_sensitivity);
85 SHOW(my_cfg, max_intra_bitrate_pct);
86 SHOW(my_cfg, tune_content);
87
88 SHOW(cfg, g_usage);
89 SHOW(cfg, g_threads);
90 SHOW(cfg, g_profile);
91 SHOW(cfg, g_w);
92 SHOW(cfg, g_h);
93 SHOW(cfg, g_bit_depth);
94 SHOW(cfg, g_input_bit_depth);
95 SHOW(cfg, g_timebase.num);
96 SHOW(cfg, g_timebase.den);
97 SHOW(cfg, g_error_resilient);
98 SHOW(cfg, g_pass);
99 SHOW(cfg, g_lag_in_frames);
100 SHOW(cfg, rc_dropframe_thresh);
101 SHOW(cfg, rc_resize_allowed);
102 SHOW(cfg, rc_scaled_width);
103 SHOW(cfg, rc_scaled_height);
104 SHOW(cfg, rc_resize_up_thresh);
105 SHOW(cfg, rc_resize_down_thresh);
106 SHOW(cfg, rc_end_usage);
107 SHOW(cfg, rc_target_bitrate);
108 SHOW(cfg, rc_min_quantizer);
109 SHOW(cfg, rc_max_quantizer);
110 SHOW(cfg, rc_undershoot_pct);
111 SHOW(cfg, rc_overshoot_pct);
112 SHOW(cfg, rc_buf_sz);
113 SHOW(cfg, rc_buf_initial_sz);
114 SHOW(cfg, rc_buf_optimal_sz);
115 SHOW(cfg, rc_2pass_vbr_bias_pct);
116 SHOW(cfg, rc_2pass_vbr_minsection_pct);
117 SHOW(cfg, rc_2pass_vbr_maxsection_pct);
118 SHOW(cfg, kf_mode);
119 SHOW(cfg, kf_min_dist);
120 SHOW(cfg, kf_max_dist);
121 SHOW(cfg, ss_number_layers);
122 SHOW(cfg, ts_number_layers);
123 SHOW(cfg, ts_periodicity);
124 SHOW(cfg, temporal_layering_mode);
125
126 if (my_cfg->codecs) {
127 switch_event_header_t *hp;
128
129 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "======== Codec specific profiles ========\n");
130
131 for (hp = my_cfg->codecs->headers; hp; hp = hp->next) {
132 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " %-28s = %s\n", hp->name, hp->value);
133 }
134 }
135 }
136
137 /* http://tools.ietf.org/html/draft-ietf-payload-vp8-10
138
139 The first octets after the RTP header are the VP8 payload descriptor, with the following structure.
140 #endif
141
142 0 1 2 3 4 5 6 7
143 +-+-+-+-+-+-+-+-+
144 |X|R|N|S|R| PID | (REQUIRED)
145 +-+-+-+-+-+-+-+-+
146 X: |I|L|T|K| RSV | (OPTIONAL)
147 +-+-+-+-+-+-+-+-+
148 I: |M| PictureID | (OPTIONAL)
149 +-+-+-+-+-+-+-+-+
150 L: | TL0PICIDX | (OPTIONAL)
151 +-+-+-+-+-+-+-+-+
152 T/K:|TID|Y| KEYIDX | (OPTIONAL)
153 +-+-+-+-+-+-+-+-+
154
155
156 VP8 Payload Header
157
158 0 1 2 3 4 5 6 7
159 +-+-+-+-+-+-+-+-+
160 |Size0|H| VER |P|
161 +-+-+-+-+-+-+-+-+
162 | Size1 |
163 +-+-+-+-+-+-+-+-+
164 | Size2 |
165 +-+-+-+-+-+-+-+-+
166 | Bytes 4..N of |
167 | VP8 payload |
168 : :
169 +-+-+-+-+-+-+-+-+
170 | OPTIONAL RTP |
171 | padding |
172 : :
173 +-+-+-+-+-+-+-+-+
174 */
175
176
177 #ifdef _MSC_VER
178 #pragma pack(push, r1, 1)
179 #endif
180
181 #if SWITCH_BYTE_ORDER == __BIG_ENDIAN
182
183 typedef struct {
184 unsigned extended:1;
185 unsigned reserved1:1;
186 unsigned non_referenced:1;
187 unsigned start:1;
188 unsigned reserved2:1;
189 unsigned pid:3;
190 unsigned I:1;
191 unsigned L:1;
192 unsigned T:1;
193 unsigned K:1;
194 unsigned RSV:4;
195 unsigned M:1;
196 unsigned PID:15;
197 unsigned TL0PICIDX:8;
198 unsigned TID:2;
199 unsigned Y:1;
200 unsigned KEYIDX:5;
201 } vp8_payload_descriptor_t;
202
203 typedef struct {
204 unsigned have_pid:1;
205 unsigned have_p_layer:1;
206 unsigned have_layer_ind:1;
207 unsigned is_flexible:1;
208 unsigned start:1;
209 unsigned end:1;
210 unsigned have_ss:1;
211 unsigned zero:1;
212 } vp9_payload_descriptor_t;
213
214 typedef struct {
215 unsigned n_s:3;
216 unsigned y:1;
217 unsigned g:1;
218 unsigned zero:3;
219 } vp9_ss_t;
220
221 typedef struct {
222 unsigned t:3;
223 unsigned u:1;
224 unsigned r:2;
225 unsigned zero:2;
226 } vp9_n_g_t;
227
228 typedef struct {
229 unsigned temporal_id:3;
230 unsigned temporal_up_switch:1;
231 unsigned spatial_id:3;
232 unsigned inter_layer_predicted:1;
233 } vp9_p_layer_t;
234
235 #else /* ELSE LITTLE */
236
237 typedef struct {
238 unsigned pid:3;
239 unsigned reserved2:1;
240 unsigned start:1;
241 unsigned non_referenced:1;
242 unsigned reserved1:1;
243 unsigned extended:1;
244 unsigned RSV:4;
245 unsigned K:1;
246 unsigned T:1;
247 unsigned L:1;
248 unsigned I:1;
249 unsigned PID:15;
250 unsigned M:1;
251 unsigned TL0PICIDX:8;
252 unsigned KEYIDX:5;
253 unsigned Y:1;
254 unsigned TID:2;
255 } vp8_payload_descriptor_t;
256
257 typedef struct {
258 unsigned zero:1;
259 unsigned have_ss:1;
260 unsigned end:1;
261 unsigned start:1;
262 unsigned is_flexible:1;
263 unsigned have_layer_ind:1;
264 unsigned have_p_layer:1;
265 unsigned have_pid:1;
266 } vp9_payload_descriptor_t;
267
268 typedef struct {
269 unsigned zero:3;
270 unsigned g:1;
271 unsigned y:1;
272 unsigned n_s:3;
273 } vp9_ss_t;
274
275 typedef struct {
276 unsigned zero:2;
277 unsigned r:2;
278 unsigned u:1;
279 unsigned t:3;
280 } vp9_n_g_t;
281
282 typedef struct {
283 unsigned inter_layer_predicted:1;
284 unsigned spatial_id:3;
285 unsigned temporal_up_switch:1;
286 unsigned temporal_id:3;
287 } vp9_p_layer_t;
288
289 #endif
290
291 typedef union {
292 vp8_payload_descriptor_t vp8;
293 vp9_payload_descriptor_t vp9;
294 } vpx_payload_descriptor_t;
295
296 #define kMaxVp9NumberOfSpatialLayers 16
297
298 typedef struct {
299 switch_bool_t has_received_sli;
300 uint8_t picture_id_sli;
301 switch_bool_t has_received_rpsi;
302 uint64_t picture_id_rpsi;
303 int16_t picture_id; // Negative value to skip pictureId.
304
305 switch_bool_t inter_pic_predicted; // This layer frame is dependent on previously
306 // coded frame(s).
307 switch_bool_t flexible_mode;
308 switch_bool_t ss_data_available;
309
310 int tl0_pic_idx; // Negative value to skip tl0PicIdx.
311 uint8_t temporal_idx;
312 uint8_t spatial_idx;
313 switch_bool_t temporal_up_switch;
314 switch_bool_t inter_layer_predicted; // Frame is dependent on directly lower spatial
315 // layer frame.
316 uint8_t gof_idx;
317
318 // SS data.
319 size_t num_spatial_layers;
320 switch_bool_t spatial_layer_resolution_present;
321 uint16_t width[kMaxVp9NumberOfSpatialLayers];
322 uint16_t height[kMaxVp9NumberOfSpatialLayers];
323 // GofInfoVP9 gof;
324 } vp9_info_t;
325
326
327 #ifdef _MSC_VER
328 #pragma pack(pop, r1)
329 #endif
330
331
332 #define __IS_VP8_KEY_FRAME(byte) !(((byte) & 0x01))
IS_VP8_KEY_FRAME(uint8_t * data)333 static inline int IS_VP8_KEY_FRAME(uint8_t *data)
334 {
335 uint8_t S;
336 uint8_t DES;
337 uint8_t PID;
338
339 DES = *data;
340 data++;
341 S = DES & 0x10;
342 PID = DES & 0x07;
343
344 if (DES & 0x80) { // X
345 uint8_t X = *data;
346 data++;
347 if (X & 0x80) { // I
348 uint8_t M = (*data) & 0x80;
349 data++;
350 if (M) data++;
351 }
352 if (X & 0x40) data++; // L
353 if (X & 0x30) data++; // T/K
354 }
355
356 if (S && (PID == 0)) {
357 return __IS_VP8_KEY_FRAME(*data);
358 } else {
359 // if (PID > 0) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "PID: %d\n", PID);
360 return 0;
361 }
362 }
363
364 #define IS_VP9_KEY_FRAME(byte) ((((byte) & 0x40) == 0) && ((byte) & 0x0A))
365 #define IS_VP9_START_PKT(byte) ((byte) & 0x08)
366
367 #ifdef WIN32
368 #undef SWITCH_MOD_DECLARE_DATA
369 #define SWITCH_MOD_DECLARE_DATA __declspec(dllexport)
370 #endif
371 SWITCH_MODULE_LOAD_FUNCTION(mod_vpx_load);
372 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_vpx_shutdown);
373 SWITCH_MODULE_DEFINITION(CORE_VPX_MODULE, mod_vpx_load, mod_vpx_shutdown, NULL);
374
375 struct vpx_context {
376 int debug;
377 switch_codec_t *codec;
378 int is_vp9;
379 vp9_info_t vp9;
380 vpx_codec_iface_t *encoder_interface;
381 vpx_codec_iface_t *decoder_interface;
382 unsigned int flags;
383 switch_codec_settings_t codec_settings;
384 unsigned int bandwidth;
385 vpx_codec_enc_cfg_t config;
386 switch_time_t last_key_frame;
387
388 vpx_codec_ctx_t encoder;
389 uint8_t encoder_init;
390 vpx_image_t *pic;
391 switch_bool_t force_key_frame;
392 int fps;
393 int format;
394 int intra_period;
395 int num;
396 int partition_index;
397 const vpx_codec_cx_pkt_t *pkt;
398 vpx_codec_iter_t enc_iter;
399 vpx_codec_iter_t dec_iter;
400 uint32_t last_ts;
401 switch_time_t last_ms;
402 vpx_codec_ctx_t decoder;
403 uint8_t decoder_init;
404 int decoded_first_frame;
405 switch_buffer_t *vpx_packet_buffer;
406 int got_key_frame;
407 int no_key_frame;
408 int got_start_frame;
409 uint32_t last_received_timestamp;
410 switch_bool_t last_received_complete_picture;
411 uint16_t last_received_seq;
412 int need_key_frame;
413 int need_encoder_reset;
414 int need_decoder_reset;
415 int32_t change_bandwidth;
416 uint64_t framecount;
417 switch_memory_pool_t *pool;
418 switch_buffer_t *pbuffer;
419 switch_time_t start_time;
420 switch_image_t *patch_img;
421 int16_t picture_id;
422 };
423 typedef struct vpx_context vpx_context_t;
424
425 #define MAX_PROFILES 100
426
427 struct vpx_globals {
428 int debug;
429 uint32_t max_bitrate;
430 uint32_t rtp_slice_size;
431 uint32_t key_frame_min_freq;
432
433 uint32_t dec_threads;
434 uint32_t enc_threads;
435
436 my_vpx_cfg_t *profiles[MAX_PROFILES];
437 };
438
439 struct vpx_globals vpx_globals = { 0 };
440
441 static my_vpx_cfg_t *find_cfg_profile(const char *name, switch_bool_t reconfig);
442 static void parse_profile(my_vpx_cfg_t *my_cfg, switch_xml_t profile, int codec_type);
443
init_decoder(switch_codec_t * codec)444 static switch_status_t init_decoder(switch_codec_t *codec)
445 {
446 vpx_context_t *context = (vpx_context_t *)codec->private_info;
447
448 //if (context->decoder_init) {
449 // vpx_codec_destroy(&context->decoder);
450 // context->decoder_init = 0;
451 //}
452
453 if (context->flags & SWITCH_CODEC_FLAG_DECODE && !context->decoder_init) {
454 vpx_codec_dec_cfg_t cfg = {0, 0, 0};
455 vpx_codec_flags_t dec_flags = 0;
456 vp8_postproc_cfg_t ppcfg;
457 my_vpx_cfg_t *my_cfg = NULL;
458 vpx_codec_err_t err;
459
460 if (context->is_vp9) {
461 my_cfg = find_cfg_profile("vp9", SWITCH_FALSE);
462 } else {
463 my_cfg = find_cfg_profile("vp8", SWITCH_FALSE);
464 }
465
466 if (!my_cfg) return SWITCH_STATUS_FALSE;
467
468 cfg.threads = my_cfg->dec_cfg.threads;
469
470 if ((err = vpx_codec_dec_init(&context->decoder, context->decoder_interface, &cfg, dec_flags)) != VPX_CODEC_OK) {
471 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_ERROR,
472 "VPX decoder %s codec init error: [%d:%s:%s]\n",
473 vpx_codec_iface_name(context->decoder_interface),
474 err, vpx_codec_error(&context->decoder), vpx_codec_error_detail(&context->decoder));
475 return SWITCH_STATUS_FALSE;
476 }
477
478 context->last_ts = 0;
479 context->last_received_timestamp = 0;
480 context->last_received_complete_picture = 0;
481 context->last_received_seq = 0;
482 context->decoder_init = 1;
483 context->got_key_frame = 0;
484 context->no_key_frame = 0;
485 context->got_start_frame = 0;
486 // the types of post processing to be done, should be combination of "vp8_postproc_level"
487 ppcfg.post_proc_flag = VP8_DEBLOCK;//VP8_DEMACROBLOCK | VP8_DEBLOCK;
488 // the strength of deblocking, valid range [0, 16]
489 ppcfg.deblocking_level = 1;
490 // Set deblocking settings
491 vpx_codec_control(&context->decoder, VP8_SET_POSTPROC, &ppcfg);
492
493 if (context->vpx_packet_buffer) {
494 switch_buffer_zero(context->vpx_packet_buffer);
495 } else {
496 switch_buffer_create_dynamic(&context->vpx_packet_buffer, 512, 512, 0);
497 }
498 }
499
500 return SWITCH_STATUS_SUCCESS;
501 }
502
CODEC_TYPE(const char * string)503 static int CODEC_TYPE(const char *string)
504 {
505 if (!strcmp(string, "vp8")) {
506 return CODEC_TYPE_VP8;
507 } else if (!strcmp(string, "vp9")) {
508 return CODEC_TYPE_VP9;
509 }
510
511 return CODEC_TYPE_ANY;
512 }
513
parse_codec_specific_profile(my_vpx_cfg_t * my_cfg,const char * codec_name)514 static void parse_codec_specific_profile(my_vpx_cfg_t *my_cfg, const char *codec_name)
515 {
516 switch_xml_t cfg = NULL;
517 switch_xml_t xml = switch_xml_open_cfg("vpx.conf", &cfg, NULL);
518 switch_xml_t profiles = cfg ? switch_xml_child(cfg, "profiles") : NULL;
519
520 // open config and find the profile to parse
521 if (profiles) {
522 switch_event_header_t *hp;
523
524 for (hp = my_cfg->codecs->headers; hp; hp = hp->next) {
525 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s: %s\n", hp->name, hp->value);
526 if (!strcmp(hp->name, codec_name)) {
527 switch_xml_t profile;
528 for (profile = switch_xml_child(profiles, "profile"); profile; profile = profile->next) {
529 const char *name = switch_xml_attr(profile, "name");
530
531 if (!strcmp(hp->value, name)) {
532 parse_profile(my_cfg, profile, CODEC_TYPE(codec_name));
533 }
534 }
535 }
536 }
537 }
538
539 if (xml) switch_xml_free(xml);
540 }
541
init_encoder(switch_codec_t * codec)542 static switch_status_t init_encoder(switch_codec_t *codec)
543 {
544 vpx_context_t *context = (vpx_context_t *)codec->private_info;
545 vpx_codec_enc_cfg_t *config = &context->config;
546 my_vpx_cfg_t *my_cfg = NULL;
547 vpx_codec_err_t err;
548 char *codec_name = "vp8";
549
550 if (context->is_vp9) {
551 codec_name = "vp9";
552 }
553
554 if (!zstr(context->codec_settings.video.config_profile_name)) {
555 my_cfg = find_cfg_profile(context->codec_settings.video.config_profile_name, SWITCH_FALSE);
556 }
557
558 if (!my_cfg) {
559 my_cfg = find_cfg_profile(codec_name, SWITCH_FALSE);
560 }
561
562 if (!my_cfg) return SWITCH_STATUS_FALSE;
563
564 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "config: %s\n", my_cfg->name);
565
566 if (context->is_vp9) {
567 my_cfg->enc_cfg.g_profile = 0; // default build of VP9 only support 0, TODO: remove this
568 }
569
570 if (my_cfg->codecs) {
571 parse_codec_specific_profile(my_cfg, codec_name);
572 }
573
574 if (vpx_globals.debug) show_config(my_cfg, &my_cfg->enc_cfg);
575
576 if (!context->codec_settings.video.width) {
577 context->codec_settings.video.width = 1280;
578 }
579
580 if (!context->codec_settings.video.height) {
581 context->codec_settings.video.height = 720;
582 }
583
584 if (context->codec_settings.video.bandwidth == -1) {
585 context->codec_settings.video.bandwidth = 0;
586 }
587
588 if (context->codec_settings.video.bandwidth) {
589 context->bandwidth = context->codec_settings.video.bandwidth;
590 } else {
591 context->bandwidth = switch_calc_bitrate(context->codec_settings.video.width, context->codec_settings.video.height, 1, 15);
592 }
593
594 if (context->bandwidth > vpx_globals.max_bitrate) {
595 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_WARNING, "REQUESTED BITRATE TRUNCATED FROM %d TO %d\n", context->bandwidth, vpx_globals.max_bitrate);
596 context->bandwidth = vpx_globals.max_bitrate;
597 }
598
599 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_NOTICE,
600 "VPX encoder reset (WxH/BW) from %dx%d/%u to %dx%d/%u\n",
601 config->g_w, config->g_h, config->rc_target_bitrate,
602 context->codec_settings.video.width, context->codec_settings.video.height, context->bandwidth);
603
604 context->pkt = NULL;
605 context->start_time = switch_micro_time_now();
606
607 *config = my_cfg->enc_cfg; // reset whole config to current defaults
608
609 config->g_w = context->codec_settings.video.width;
610 config->g_h = context->codec_settings.video.height;
611 config->rc_target_bitrate = context->bandwidth;
612
613 if (context->is_vp9) {
614 if (my_cfg->lossless) {
615 config->rc_min_quantizer = 0;
616 config->rc_max_quantizer = 0;
617 }
618 }
619
620 if (context->encoder_init) {
621 if ((err = vpx_codec_enc_config_set(&context->encoder, config)) != VPX_CODEC_OK) {
622 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_ERROR,
623 "VPX encoder %s codec reconf error: [%d:%s:%s]\n",
624 vpx_codec_iface_name(context->encoder_interface),
625 err, vpx_codec_error(&context->encoder), vpx_codec_error_detail(&context->encoder));
626 return SWITCH_STATUS_FALSE;
627 }
628 } else if (context->flags & SWITCH_CODEC_FLAG_ENCODE) {
629 if (vpx_globals.debug) {
630 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_INFO, "VPX encoder %s settings:\n", vpx_codec_iface_name(context->encoder_interface));
631 show_config(my_cfg, config);
632 }
633
634 if ((err = vpx_codec_enc_init(&context->encoder, context->encoder_interface, config, 0 & VPX_CODEC_USE_OUTPUT_PARTITION)) != VPX_CODEC_OK) {
635 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_ERROR,
636 "VPX encoder %s codec init error: [%d:%s:%s]\n",
637 vpx_codec_iface_name(context->encoder_interface),
638 err, vpx_codec_error(&context->encoder), vpx_codec_error_detail(&context->encoder));
639 return SWITCH_STATUS_FALSE;
640 }
641
642 context->encoder_init = 1;
643
644 vpx_codec_control(&context->encoder, VP8E_SET_TOKEN_PARTITIONS, my_cfg->token_parts);
645 vpx_codec_control(&context->encoder, VP8E_SET_CPUUSED, my_cfg->cpuused);
646 vpx_codec_control(&context->encoder, VP8E_SET_STATIC_THRESHOLD, my_cfg->static_thresh);
647
648 if (context->is_vp9) {
649 if (my_cfg->lossless) {
650 vpx_codec_control(&context->encoder, VP9E_SET_LOSSLESS, 1);
651 }
652
653 vpx_codec_control(&context->encoder, VP9E_SET_TUNE_CONTENT, my_cfg->tune_content);
654 } else {
655 vpx_codec_control(&context->encoder, VP8E_SET_NOISE_SENSITIVITY, my_cfg->noise_sensitivity);
656
657 if (my_cfg->max_intra_bitrate_pct) {
658 vpx_codec_control(&context->encoder, VP8E_SET_MAX_INTRA_BITRATE_PCT, my_cfg->max_intra_bitrate_pct);
659 }
660 }
661 }
662
663 return SWITCH_STATUS_SUCCESS;
664 }
665
switch_vpx_init(switch_codec_t * codec,switch_codec_flag_t flags,const switch_codec_settings_t * codec_settings)666 static switch_status_t switch_vpx_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
667 {
668 vpx_context_t *context = NULL;
669 int encoding, decoding;
670
671 encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
672 decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
673
674 if (!(encoding || decoding) || ((context = switch_core_alloc(codec->memory_pool, sizeof(*context))) == 0)) {
675 return SWITCH_STATUS_FALSE;
676 }
677
678 memset(context, 0, sizeof(*context));
679 context->flags = flags;
680 codec->private_info = context;
681 context->pool = codec->memory_pool;
682
683 if (codec_settings) {
684 context->codec_settings = *codec_settings;
685 }
686
687 if (!strcmp(codec->implementation->iananame, "VP9")) {
688 context->is_vp9 = 1;
689 context->encoder_interface = vpx_codec_vp9_cx();
690 context->decoder_interface = vpx_codec_vp9_dx();
691 } else {
692 context->encoder_interface = vpx_codec_vp8_cx();
693 context->decoder_interface = vpx_codec_vp8_dx();
694 }
695
696 if (codec->fmtp_in) {
697 codec->fmtp_out = switch_core_strdup(codec->memory_pool, codec->fmtp_in);
698 }
699
700 context->codec_settings.video.width = 320;
701 context->codec_settings.video.height = 240;
702
703 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_DEBUG, "VPX VER:%s VPX_IMAGE_ABI_VERSION:%d VPX_CODEC_ABI_VERSION:%d\n",
704 vpx_codec_version_str(), VPX_IMAGE_ABI_VERSION, VPX_CODEC_ABI_VERSION);
705
706 if (!context->is_vp9) {
707 context->picture_id = 13; // picture Id may start from random value and must be incremented on each frame
708 } else {
709 context->vp9.picture_id = 13;
710 }
711
712 return SWITCH_STATUS_SUCCESS;
713 }
714
consume_partition(vpx_context_t * context,switch_frame_t * frame)715 static switch_status_t consume_partition(vpx_context_t *context, switch_frame_t *frame)
716 {
717 vpx_payload_descriptor_t *payload_descriptor;
718 uint8_t *body, *c = NULL;
719 uint32_t hdrlen = 0, payload_size = 0, max_payload_size = 0, start = 0, key = 0;
720 switch_size_t remaining_bytes = 0;
721 switch_status_t status;
722
723 if (!context->pkt) {
724 if ((context->pkt = vpx_codec_get_cx_data(&context->encoder, &context->enc_iter))) {
725 start = 1;
726 if (!context->pbuffer) {
727 switch_buffer_create_partition(context->pool, &context->pbuffer, context->pkt->data.frame.buf, context->pkt->data.frame.sz);
728 } else {
729 switch_buffer_set_partition_data(context->pbuffer, context->pkt->data.frame.buf, context->pkt->data.frame.sz);
730 }
731 }
732 }
733
734 if (context->pbuffer) {
735 remaining_bytes = switch_buffer_inuse(context->pbuffer);
736 }
737
738 if (!context->pkt || context->pkt->kind != VPX_CODEC_CX_FRAME_PKT || !remaining_bytes) {
739 frame->datalen = 0;
740 frame->m = 1;
741 context->pkt = NULL;
742 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "writing 0 bytes\n");
743 return SWITCH_STATUS_SUCCESS;
744 }
745
746 key = (context->pkt->data.frame.flags & VPX_FRAME_IS_KEY);
747
748 #if 0
749 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "flags: %x pts: %lld duration:%lu partition_id: %d\n",
750 context->pkt->data.frame.flags, context->pkt->data.frame.pts, context->pkt->data.frame.duration, context->pkt->data.frame.partition_id);
751 #endif
752
753 /* reset header */
754 *(uint8_t *)frame->data = 0;
755 payload_descriptor = (vpx_payload_descriptor_t *) frame->data;
756 memset(payload_descriptor, 0, sizeof(*payload_descriptor));
757
758
759 if (context->is_vp9) {
760 hdrlen = 1; /* Send VP9 with 1 byte REQUIRED header. */
761 } else {
762 hdrlen = 4; /* Send VP8 with 4 byte extended header, includes 1 byte REQUIRED header, 1 byte X header and 2 bytes of I header with picture_id. */
763 }
764
765 body = ((uint8_t *)frame->data) + hdrlen;
766
767 if (context->is_vp9) {
768 payload_descriptor->vp9.start = start;
769
770 if (1) {
771 // payload_descriptor->vp9.have_p_layer = key; // key?
772 payload_descriptor->vp9.have_pid = 1;
773
774 if (payload_descriptor->vp9.have_pid) {
775 if (context->vp9.picture_id > 0x7f) {
776 *body++ = (context->vp9.picture_id >> 8) | 0x80;
777 *body++ = context->vp9.picture_id & 0xff;
778 hdrlen += 2;
779 } else {
780 *body++ = context->vp9.picture_id;
781 hdrlen++;
782 }
783 }
784
785 if (key) {
786 vp9_ss_t *ss = (vp9_ss_t *)body;
787
788 payload_descriptor->vp9.have_ss = 1;
789 payload_descriptor->vp9.have_p_layer = 0;
790 ss->n_s = 0;
791 ss->g = 0;
792 ss->y = 0;
793 ss->zero = 0;
794 body++;
795 hdrlen++;
796
797 if (0) { // y ?
798 uint16_t *w;
799 uint16_t *h;
800
801 ss->y = 1;
802
803 w = (uint16_t *)body;
804 body+=2;
805 h = (uint16_t *)body;
806 body+=2;
807
808 *w = (uint16_t)context->codec_settings.video.width;
809 *h = (uint16_t)context->codec_settings.video.height;
810
811 hdrlen += (ss->n_s + 1) * 4;
812 }
813 } else {
814 payload_descriptor->vp9.have_p_layer = 1;
815 }
816 }
817 }
818
819 if (!context->is_vp9) {
820 payload_descriptor->vp8.start = start;
821
822 payload_descriptor->vp8.extended = 1; /* REQUIRED header. */
823
824 payload_descriptor->vp8.I = 1; /* X header. */
825
826 payload_descriptor->vp8.M = 1; /* I header. */
827 c = ((uint8_t *)frame->data) + 2;
828 *c++ = (context->picture_id >> 8) | 0x80;
829 *c = context->picture_id & 0xff;
830
831 payload_descriptor->vp8.L = 0;
832 payload_descriptor->vp8.TL0PICIDX = 0;
833
834 payload_descriptor->vp8.T = 0;
835 payload_descriptor->vp8.TID = 0;
836 payload_descriptor->vp8.Y = 0;
837 payload_descriptor->vp8.K = 0;
838 payload_descriptor->vp8.KEYIDX = 0;
839 }
840
841 /*
842 Try to split payload to packets evenly(with largest at the end) up to vpx_globals.rtp_slice_size,
843 (assume hdrlen constant across all packets of the same picture).
844 It keeps packets being transmitted in order.
845 Without it last (and thus the smallest one) packet usually arrive out of order
846 (before the previous one)
847 */
848 max_payload_size = vpx_globals.rtp_slice_size - hdrlen;
849 payload_size = remaining_bytes / ((remaining_bytes + max_payload_size - 1) / max_payload_size);
850
851 if (remaining_bytes <= payload_size) {
852 switch_buffer_read(context->pbuffer, body, remaining_bytes);
853 context->pkt = NULL;
854 frame->datalen = hdrlen + remaining_bytes;
855 frame->m = 1;
856
857 // increment and wrap picture_id (if needed) after the last picture's packet
858 if (context->is_vp9) {
859 context->vp9.picture_id++;
860 if ((uint16_t)context->vp9.picture_id > 0x7fff) {
861 context->vp9.picture_id = 0;
862 }
863 } else {
864 context->picture_id++;
865 if ((uint16_t)context->picture_id > 0x7fff) {
866 context->picture_id = 0;
867 }
868 }
869
870 status = SWITCH_STATUS_SUCCESS;
871 } else {
872 switch_buffer_read(context->pbuffer, body, payload_size);
873 frame->datalen = hdrlen + payload_size;
874 frame->m = 0;
875 status = SWITCH_STATUS_MORE_DATA;
876 }
877
878 if (frame->m && context->is_vp9) {
879 payload_descriptor->vp9.end = 1;
880 }
881
882 return status;
883 }
884
reset_codec_encoder(switch_codec_t * codec)885 static switch_status_t reset_codec_encoder(switch_codec_t *codec)
886 {
887 vpx_context_t *context = (vpx_context_t *)codec->private_info;
888
889 if (context->encoder_init) {
890 vpx_codec_destroy(&context->encoder);
891 }
892 context->last_ts = 0;
893 context->last_ms = 0;
894 context->framecount = 0;
895 context->encoder_init = 0;
896 context->pkt = NULL;
897 return init_encoder(codec);
898 }
899
switch_vpx_encode(switch_codec_t * codec,switch_frame_t * frame)900 static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_frame_t *frame)
901 {
902 vpx_context_t *context = (vpx_context_t *)codec->private_info;
903 int width = 0;
904 int height = 0;
905 uint32_t dur;
906 int64_t pts;
907 vpx_enc_frame_flags_t vpx_flags = 0;
908 switch_time_t now;
909 vpx_codec_err_t err;
910
911 if (frame->flags & SFF_SAME_IMAGE) {
912 return consume_partition(context, frame);
913 }
914
915 if (context->need_encoder_reset != 0) {
916 if (reset_codec_encoder(codec) != SWITCH_STATUS_SUCCESS) {
917 return SWITCH_STATUS_FALSE;
918 }
919 context->need_encoder_reset = 0;
920 }
921
922 if (frame->img->d_h > 1) {
923 width = frame->img->d_w;
924 height = frame->img->d_h;
925 } else {
926 width = frame->img->w;
927 height = frame->img->h;
928 }
929
930 if (context->codec_settings.video.width != width || context->codec_settings.video.height != height) {
931 context->codec_settings.video.width = width;
932 context->codec_settings.video.height = height;
933 reset_codec_encoder(codec);
934 frame->flags |= SFF_PICTURE_RESET;
935 context->need_key_frame = 3;
936 }
937
938 if (!context->encoder_init) {
939 if (init_encoder(codec) != SWITCH_STATUS_SUCCESS) {
940 return SWITCH_STATUS_FALSE;
941 }
942 }
943
944 if (context->change_bandwidth) {
945 context->codec_settings.video.bandwidth = context->change_bandwidth;
946 context->change_bandwidth = 0;
947 if (init_encoder(codec) != SWITCH_STATUS_SUCCESS) {
948 return SWITCH_STATUS_FALSE;
949 }
950 }
951
952 now = switch_time_now();
953
954 if (context->need_key_frame > 0) {
955 // force generate a key frame
956 if (!context->last_key_frame || (now - context->last_key_frame) > vpx_globals.key_frame_min_freq) {
957 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), VPX_SWITCH_LOG_LEVEL,
958 "VPX encoder keyframe request\n");
959 vpx_flags |= VPX_EFLAG_FORCE_KF;
960 context->need_key_frame = 0;
961 context->last_key_frame = now;
962 }
963 }
964
965 context->framecount++;
966
967 pts = (now - context->start_time) / 1000;
968 //pts = frame->timestamp;
969
970 dur = context->last_ms ? (now - context->last_ms) / 1000 : pts;
971
972 if ((err = vpx_codec_encode(&context->encoder,
973 (vpx_image_t *) frame->img,
974 pts,
975 dur,
976 vpx_flags,
977 VPX_DL_REALTIME)) != VPX_CODEC_OK) {
978 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_ERROR, "VPX encode error [%d:%s:%s]\n",
979 err, vpx_codec_error(&context->encoder), vpx_codec_error_detail(&context->encoder));
980 frame->datalen = 0;
981 return SWITCH_STATUS_FALSE;
982 }
983
984 context->enc_iter = NULL;
985 context->last_ts = frame->timestamp;
986 context->last_ms = now;
987
988 return consume_partition(context, frame);
989 }
990
buffer_vp8_packets(vpx_context_t * context,switch_frame_t * frame)991 static switch_status_t buffer_vp8_packets(vpx_context_t *context, switch_frame_t *frame)
992 {
993 uint8_t *data = frame->data;
994 uint8_t S;
995 uint8_t DES;
996 // uint8_t PID;
997 int len;
998
999 if (context->debug > 0) {
1000 switch_log_printf(SWITCH_CHANNEL_LOG, context->debug,
1001 "VIDEO VPX: seq: %d ts: %u len: %u %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x mark: %d\n",
1002 frame->seq, frame->timestamp, frame->datalen,
1003 *((uint8_t *)data), *((uint8_t *)data + 1),
1004 *((uint8_t *)data + 2), *((uint8_t *)data + 3),
1005 *((uint8_t *)data + 4), *((uint8_t *)data + 5),
1006 *((uint8_t *)data + 6), *((uint8_t *)data + 7),
1007 *((uint8_t *)data + 8), *((uint8_t *)data + 9),
1008 *((uint8_t *)data + 10), frame->m);
1009 }
1010
1011 DES = *data;
1012 data++;
1013 S = (DES & 0x10);
1014 // PID = DES & 0x07;
1015
1016 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DATA LEN %d S BIT %d PID: %d\n", frame->datalen, S, PID);
1017
1018 if (DES & 0x80) { // X
1019 uint8_t X = *data;
1020 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "X BIT SET\n");
1021 data++;
1022 if (X & 0x80) { // I
1023 uint8_t M = (*data) & 0x80;
1024 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "I BIT SET\n");
1025 data++;
1026 if (M) {
1027 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "M BIT SET\n");
1028 data++;
1029 }
1030 }
1031 if (X & 0x40) {
1032 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "L BIT SET\n");
1033 data++; // L
1034 }
1035 if (X & 0x30) {
1036 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "T/K BIT SET\n");
1037 data++; // T/K
1038 }
1039 }
1040
1041 if (!switch_buffer_inuse(context->vpx_packet_buffer) && !S) {
1042 if (context->got_key_frame > 0) {
1043 context->got_key_frame = 0;
1044 context->got_start_frame = 0;
1045 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG2, "packet loss?\n");
1046 }
1047 return SWITCH_STATUS_MORE_DATA;
1048 }
1049
1050 if (S) {
1051 switch_buffer_zero(context->vpx_packet_buffer);
1052 context->last_received_timestamp = frame->timestamp;
1053 #if 0
1054 if (PID == 0) {
1055 key = __IS_VP8_KEY_FRAME(*data);
1056 }
1057 #endif
1058 }
1059
1060 len = frame->datalen - (data - (uint8_t *)frame->data);
1061 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POST PARSE: DATA LEN %d KEY %d KEYBYTE = %0x\n", len, key, *data);
1062
1063 if (len <= 0) {
1064 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid packet %d\n", len);
1065 return SWITCH_STATUS_RESTART;
1066 }
1067
1068 if (context->last_received_timestamp != frame->timestamp) {
1069 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG2, "wrong timestamp %u, expect %u, packet loss?\n", frame->timestamp, context->last_received_timestamp);
1070 switch_buffer_zero(context->vpx_packet_buffer);
1071 return SWITCH_STATUS_RESTART;
1072 }
1073
1074 switch_buffer_write(context->vpx_packet_buffer, data, len);
1075 return SWITCH_STATUS_SUCCESS;
1076 }
1077
1078 // https://tools.ietf.org/id/draft-ietf-payload-vp9-01.txt
1079
buffer_vp9_packets(vpx_context_t * context,switch_frame_t * frame)1080 static switch_status_t buffer_vp9_packets(vpx_context_t *context, switch_frame_t *frame)
1081 {
1082 uint8_t *data = (uint8_t *)frame->data;
1083 uint8_t *vp9 = (uint8_t *)frame->data;
1084 vp9_payload_descriptor_t *desc = (vp9_payload_descriptor_t *)vp9;
1085 int len = 0;
1086
1087 if (context->debug > 0) {
1088 switch_log_printf(SWITCH_CHANNEL_LOG, frame->m ? SWITCH_LOG_ERROR : SWITCH_LOG_INFO,
1089 "[%02x %02x %02x %02x] m=%d len=%4d seq=%d ts=%u ssrc=%u "
1090 "have_pid=%d "
1091 "have_p_layer=%d "
1092 "have_layer_ind=%d "
1093 "is_flexible=%d "
1094 "start=%d "
1095 "end=%d "
1096 "have_ss=%d "
1097 "zero=%d\n",
1098 *data, *(data+1), *(data+2), *(data+3), frame->m, frame->datalen, frame->seq, frame->timestamp, frame->ssrc,
1099 desc->have_pid,
1100 desc->have_p_layer,
1101 desc->have_layer_ind,
1102 desc->is_flexible,
1103 desc->start,
1104 desc->end,
1105 desc->have_ss,
1106 desc->zero);
1107 }
1108
1109 vp9++;
1110
1111 if (desc->have_pid) {
1112 #ifdef DEBUG_VP9
1113 uint16_t pid = 0;
1114 pid = *vp9 & 0x7f; //0 bit is M , 1-7 bit is pid.
1115 #endif
1116 if (*vp9 & 0x80) { //if (M==1)
1117 vp9++;
1118 #ifdef DEBUG_VP9
1119 pid = (pid << 8) + *vp9;
1120 #endif
1121 }
1122
1123 vp9++;
1124
1125 #ifdef DEBUG_VP9
1126 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "have pid: %d start=%d end=%d\n", pid, desc->start, desc->end);
1127 #endif
1128
1129 }
1130
1131 if (desc->have_layer_ind) {
1132 #ifdef DEBUG_VP9
1133 vp9_p_layer_t *layer = (vp9_p_layer_t *)vp9;
1134
1135 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "temporal_id=%d temporal_up_switch=%d spatial_id=%d inter_layer_predicted=%d\n",
1136 layer->temporal_id, layer->temporal_up_switch, layer->spatial_id, layer->inter_layer_predicted);
1137 #endif
1138
1139 vp9++;
1140 if (!desc->is_flexible) {
1141 vp9++; // TL0PICIDX
1142 }
1143 }
1144
1145 //When P and F are both set to one, indicating a non-key frame in flexible mode
1146 if (desc->have_p_layer && desc->is_flexible) { // P & F set, P_DIFF
1147 if (*vp9 & 1) { // N
1148 vp9++;
1149 if (*vp9 & 1) { // N
1150 vp9++;
1151 if (*vp9 & 1) {
1152 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid VP9 packet!");
1153 switch_buffer_zero(context->vpx_packet_buffer);
1154 goto end;
1155 }
1156 }
1157 }
1158 vp9++;
1159 }
1160
1161 if (desc->have_ss) {
1162 vp9_ss_t *ss = (vp9_ss_t *)(vp9++);
1163
1164 #ifdef DEBUG_VP9
1165 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "have ss: %02x n_s: %d y:%d g:%d\n", *(uint8_t *)ss, ss->n_s, ss->y, ss->g);
1166 #endif
1167 if (ss->y) {
1168 int i;
1169
1170 for (i=0; i<=ss->n_s; i++) {
1171 #ifdef DEBUG_VP9
1172 int width = ntohs(*(uint16_t *)vp9);
1173 int height = ntohs(*(uint16_t *)(vp9 + 2));
1174 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "SS: %d %dx%d\n", i, width, height);
1175 #endif
1176 vp9 += 4;
1177 }
1178 }
1179
1180 if (ss->g) {
1181 int i;
1182 uint8_t ng = *vp9++; //N_G indicates the number of frames in a GOF
1183
1184 for (i = 0; ng > 0 && i < ng; i++) {
1185 vp9_n_g_t *n_g = (vp9_n_g_t *)(vp9++);
1186 vp9 += n_g->r;
1187 }
1188 }
1189 }
1190
1191 if (vp9 - data >= frame->datalen) {
1192 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Invalid VP9 Packet %" SWITCH_SSIZE_T_FMT " > %d\n", vp9 - data, frame->datalen);
1193 switch_buffer_zero(context->vpx_packet_buffer);
1194 goto end;
1195 }
1196
1197 if (!switch_buffer_inuse(context->vpx_packet_buffer)) { // start packet
1198 if (!desc->start) {
1199 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "got invalid vp9 packet, packet loss? waiting for a start packet\n");
1200 goto end;
1201 }
1202 }
1203
1204 len = frame->datalen - (vp9 - data);
1205 switch_buffer_write(context->vpx_packet_buffer, vp9, len);
1206
1207 end:
1208
1209 #ifdef DEBUG_VP9
1210 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "buffered %d bytes, buffer size: %" SWITCH_SIZE_T_FMT "\n", len, switch_buffer_inuse(context->vpx_packet_buffer));
1211 #endif
1212
1213 return SWITCH_STATUS_SUCCESS;
1214 }
1215
switch_vpx_decode(switch_codec_t * codec,switch_frame_t * frame)1216 static switch_status_t switch_vpx_decode(switch_codec_t *codec, switch_frame_t *frame)
1217 {
1218 vpx_context_t *context = (vpx_context_t *)codec->private_info;
1219 switch_size_t len;
1220 vpx_codec_ctx_t *decoder = NULL;
1221 switch_status_t status = SWITCH_STATUS_SUCCESS;
1222 int is_start = 0, is_keyframe = 0, get_refresh = 0;
1223
1224 if (context->debug > 0 && context->debug < 4) {
1225 vp9_payload_descriptor_t *desc = (vp9_payload_descriptor_t *)frame->data;
1226 uint8_t *data = frame->data;
1227 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%02x %02x %02x %02x m=%d start=%d end=%d m=%d len=%d\n",
1228 *data, *(data+1), *(data+2), *(data+3), frame->m, desc->start, desc->end, frame->m, frame->datalen);
1229 }
1230
1231 if (context->is_vp9) {
1232 is_keyframe = IS_VP9_KEY_FRAME(*(unsigned char *)frame->data);
1233 is_start = IS_VP9_START_PKT(*(unsigned char *)frame->data);
1234
1235 if (is_keyframe) {
1236 switch_log_printf(SWITCH_CHANNEL_LOG, VPX_SWITCH_LOG_LEVEL, "================Got a key frame!!!!========================\n");
1237 }
1238
1239 if (context->last_received_seq && context->last_received_seq + 1 != frame->seq) {
1240 switch_log_printf(SWITCH_CHANNEL_LOG, VPX_SWITCH_LOG_LEVEL, "Packet loss detected last=%d got=%d lost=%d\n", context->last_received_seq, frame->seq, frame->seq - context->last_received_seq);
1241 if (is_keyframe && context->vpx_packet_buffer) switch_buffer_zero(context->vpx_packet_buffer);
1242 }
1243
1244 context->last_received_seq = frame->seq;
1245 } else { // vp8
1246 is_start = (*(unsigned char *)frame->data & 0x10);
1247 is_keyframe = IS_VP8_KEY_FRAME((uint8_t *)frame->data);
1248 }
1249
1250 if (!is_keyframe && context->got_key_frame <= 0) {
1251 context->no_key_frame++;
1252 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "no keyframe, %d\n", context->no_key_frame);
1253 if (context->no_key_frame > 50) {
1254 if ((is_keyframe = is_start)) {
1255 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "no keyframe, treating start as key. frames=%d\n", context->no_key_frame);
1256 }
1257 }
1258 }
1259
1260 if (context->debug > 0 && is_keyframe) {
1261 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "GOT KEY FRAME %d\n", context->got_key_frame);
1262 }
1263
1264 if (context->need_decoder_reset != 0) {
1265 vpx_codec_destroy(&context->decoder);
1266 context->decoder_init = 0;
1267 status = init_decoder(codec);
1268 context->need_decoder_reset = 0;
1269 }
1270
1271 if (status != SWITCH_STATUS_SUCCESS) goto end;
1272
1273 if (!context->decoder_init) {
1274 status = init_decoder(codec);
1275 }
1276
1277 if (status != SWITCH_STATUS_SUCCESS) goto end;
1278
1279 if (!context->decoder_init) {
1280 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "VPX decoder is not initialized!\n");
1281 return SWITCH_STATUS_FALSE;
1282 }
1283
1284 decoder = &context->decoder;
1285
1286 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "len: %d ts: %u mark:%d\n", frame->datalen, frame->timestamp, frame->m);
1287
1288 // context->last_received_timestamp = frame->timestamp;
1289 context->last_received_complete_picture = frame->m ? SWITCH_TRUE : SWITCH_FALSE;
1290
1291 if (is_start) {
1292 context->got_start_frame = 1;
1293 }
1294
1295 if (is_keyframe) {
1296 switch_set_flag(frame, SFF_IS_KEYFRAME);
1297 if (context->got_key_frame <= 0) {
1298 context->got_key_frame = 1;
1299 context->no_key_frame = 0;
1300 } else {
1301 context->got_key_frame++;
1302 }
1303 } else if (context->got_key_frame <= 0) {
1304 if ((--context->got_key_frame % 200) == 0) {
1305 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Waiting for key frame %d\n", context->got_key_frame);
1306 }
1307
1308 get_refresh = 1;
1309
1310 if (!context->got_start_frame) {
1311 switch_goto_status(SWITCH_STATUS_MORE_DATA, end);
1312 }
1313 }
1314
1315
1316 status = context->is_vp9 ? buffer_vp9_packets(context, frame) : buffer_vp8_packets(context, frame);
1317
1318
1319 if (context->dec_iter && (frame->img = (switch_image_t *) vpx_codec_get_frame(decoder, &context->dec_iter))) {
1320 switch_goto_status(SWITCH_STATUS_SUCCESS, end);
1321 }
1322
1323 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "====READ buf:%ld got_key:%d st:%d m:%d\n", switch_buffer_inuse(context->vpx_packet_buffer), context->got_key_frame, status, frame->m);
1324
1325 len = switch_buffer_inuse(context->vpx_packet_buffer);
1326
1327 //if (frame->m && (status != SWITCH_STATUS_SUCCESS || !len)) {
1328 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "WTF????? %d %ld\n", status, len);
1329 //}
1330
1331 if (status == SWITCH_STATUS_SUCCESS && frame->m && len) {
1332 uint8_t *data;
1333 int corrupted = 0;
1334 vpx_codec_err_t err;
1335
1336 switch_buffer_peek_zerocopy(context->vpx_packet_buffer, (void *)&data);
1337
1338 context->dec_iter = NULL;
1339 err = vpx_codec_decode(decoder, data, (unsigned int)len, NULL, 0);
1340
1341 if (err != VPX_CODEC_OK) {
1342 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), (context->decoded_first_frame ? SWITCH_LOG_ERROR : VPX_SWITCH_LOG_LEVEL),
1343 "VPX error decoding %" SWITCH_SIZE_T_FMT " bytes, [%d:%s:%s]\n",
1344 len, err, vpx_codec_error(decoder), vpx_codec_error_detail(decoder));
1345
1346 if (err == VPX_CODEC_MEM_ERROR) {
1347 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_WARNING, "VPX MEM ERROR, resetting decoder!\n");
1348 context->need_decoder_reset = 1;
1349 }
1350
1351 switch_goto_status(SWITCH_STATUS_RESTART, end);
1352 } else {
1353 if (!context->decoded_first_frame) context->decoded_first_frame = 1;
1354 }
1355
1356 if (vpx_codec_control(decoder, VP8D_GET_FRAME_CORRUPTED, &corrupted) != VPX_CODEC_OK) {
1357 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_WARNING, "VPX control error!\n");
1358 switch_goto_status(SWITCH_STATUS_RESTART, end);
1359 }
1360
1361 if (corrupted) {
1362 frame->img = NULL;
1363 #ifdef DEBUG_VP9
1364 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "corrupted!!\n");
1365 #endif
1366 } else {
1367 frame->img = (switch_image_t *) vpx_codec_get_frame(decoder, &context->dec_iter);
1368
1369 #ifdef DEBUG_VP9
1370 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "decoded: %dx%d\n", frame->img->d_w, frame->img->d_h);
1371 #endif
1372 }
1373
1374 switch_buffer_zero(context->vpx_packet_buffer);
1375
1376 if (!frame->img) {
1377 //context->need_decoder_reset = 1;
1378 context->got_key_frame = 0;
1379 context->got_start_frame = 0;
1380 status = SWITCH_STATUS_RESTART;
1381 }
1382 }
1383
1384 end:
1385
1386 if (status == SWITCH_STATUS_RESTART) {
1387 switch_buffer_zero(context->vpx_packet_buffer);
1388 //context->need_decoder_reset = 1;
1389 context->got_key_frame = 0;
1390 context->got_start_frame = 0;
1391 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "RESET VPX\n");
1392 }
1393
1394 if (!frame->img || status == SWITCH_STATUS_RESTART) {
1395 status = SWITCH_STATUS_MORE_DATA;
1396 }
1397
1398 if (context->got_key_frame <= 0 || get_refresh) {
1399 switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
1400 }
1401
1402 if (frame->img && (codec->flags & SWITCH_CODEC_FLAG_VIDEO_PATCHING)) {
1403 switch_img_free(&context->patch_img);
1404 switch_img_copy(frame->img, &context->patch_img);
1405 frame->img = context->patch_img;
1406 }
1407
1408 return status;
1409 }
1410
1411
switch_vpx_control(switch_codec_t * codec,switch_codec_control_command_t cmd,switch_codec_control_type_t ctype,void * cmd_data,switch_codec_control_type_t atype,void * cmd_arg,switch_codec_control_type_t * rtype,void ** ret_data)1412 static switch_status_t switch_vpx_control(switch_codec_t *codec,
1413 switch_codec_control_command_t cmd,
1414 switch_codec_control_type_t ctype,
1415 void *cmd_data,
1416 switch_codec_control_type_t atype,
1417 void *cmd_arg,
1418 switch_codec_control_type_t *rtype,
1419 void **ret_data)
1420 {
1421
1422 vpx_context_t *context = (vpx_context_t *)codec->private_info;
1423
1424 switch(cmd) {
1425 case SCC_VIDEO_RESET:
1426 {
1427 int mask = *((int *) cmd_data);
1428 if (mask & 1) {
1429 context->need_encoder_reset = 1;
1430 }
1431 if (mask & 2) {
1432 context->need_decoder_reset = 1;
1433 }
1434 }
1435 break;
1436 case SCC_VIDEO_GEN_KEYFRAME:
1437 context->need_key_frame = 1;
1438 break;
1439 case SCC_VIDEO_BANDWIDTH:
1440 {
1441 switch(ctype) {
1442 case SCCT_INT:
1443 context->change_bandwidth = *((int *) cmd_data);
1444 break;
1445 case SCCT_STRING:
1446 {
1447 char *bwv = (char *) cmd_data;
1448 context->change_bandwidth = switch_parse_bandwidth_string(bwv);
1449 }
1450 break;
1451 default:
1452 break;
1453 }
1454 }
1455 break;
1456 case SCC_CODEC_SPECIFIC:
1457 {
1458 const char *command = (const char *)cmd_data;
1459
1460 if (ctype == SCCT_INT) {
1461 } else if (ctype == SCCT_STRING && !zstr(command)) {
1462 if (!strcasecmp(command, "VP8E_SET_CPUUSED")) {
1463 vpx_codec_control(&context->encoder, VP8E_SET_CPUUSED, *(int *)cmd_arg);
1464 } else if (!strcasecmp(command, "VP8E_SET_TOKEN_PARTITIONS")) {
1465 vpx_codec_control(&context->encoder, VP8E_SET_TOKEN_PARTITIONS, *(int *)cmd_arg);
1466 } else if (!strcasecmp(command, "VP8E_SET_NOISE_SENSITIVITY")) {
1467 vpx_codec_control(&context->encoder, VP8E_SET_NOISE_SENSITIVITY, *(int *)cmd_arg);
1468 }
1469 }
1470
1471 }
1472 break;
1473 case SCC_DEBUG:
1474 {
1475 int32_t level = *((uint32_t *) cmd_data);
1476 context->debug = level;
1477 }
1478 break;
1479 default:
1480 break;
1481 }
1482
1483
1484 return SWITCH_STATUS_SUCCESS;
1485 }
1486
1487
switch_vpx_destroy(switch_codec_t * codec)1488 static switch_status_t switch_vpx_destroy(switch_codec_t *codec)
1489 {
1490 vpx_context_t *context = (vpx_context_t *)codec->private_info;
1491
1492 if (context) {
1493
1494 switch_img_free(&context->patch_img);
1495
1496 if ((codec->flags & SWITCH_CODEC_FLAG_ENCODE)) {
1497 vpx_codec_destroy(&context->encoder);
1498 }
1499
1500 if ((codec->flags & SWITCH_CODEC_FLAG_DECODE)) {
1501 vpx_codec_destroy(&context->decoder);
1502 }
1503
1504 if (context->pic) {
1505 vpx_img_free(context->pic);
1506 context->pic = NULL;
1507 }
1508 if (context->vpx_packet_buffer) {
1509 switch_buffer_destroy(&context->vpx_packet_buffer);
1510 context->vpx_packet_buffer = NULL;
1511 }
1512 }
1513 return SWITCH_STATUS_SUCCESS;
1514 }
1515
init_vp8(my_vpx_cfg_t * my_cfg)1516 static void init_vp8(my_vpx_cfg_t *my_cfg)
1517 {
1518 vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &my_cfg->enc_cfg, 0);
1519
1520 my_cfg->dec_cfg.threads = vpx_globals.dec_threads;
1521 my_cfg->enc_cfg.g_threads = vpx_globals.enc_threads;
1522 my_cfg->static_thresh = 100;
1523 my_cfg->noise_sensitivity = 1;
1524
1525 my_cfg->cpuused = -6;
1526 my_cfg->enc_cfg.g_profile = 2;
1527 my_cfg->enc_cfg.g_timebase.num = 1;
1528 my_cfg->enc_cfg.g_timebase.den = 1000;
1529 my_cfg->enc_cfg.g_error_resilient = VPX_ERROR_RESILIENT_PARTITIONS;
1530 my_cfg->enc_cfg.rc_resize_allowed = 1;
1531 my_cfg->enc_cfg.rc_end_usage = VPX_CBR;
1532 my_cfg->enc_cfg.rc_target_bitrate = switch_parse_bandwidth_string("1mb");
1533 my_cfg->enc_cfg.rc_min_quantizer = 4;
1534 my_cfg->enc_cfg.rc_max_quantizer = 63;
1535 my_cfg->enc_cfg.rc_overshoot_pct = 50;
1536 my_cfg->enc_cfg.rc_buf_sz = 5000;
1537 my_cfg->enc_cfg.rc_buf_initial_sz = 1000;
1538 my_cfg->enc_cfg.rc_buf_optimal_sz = 1000;
1539 my_cfg->enc_cfg.kf_max_dist = 360;
1540 }
1541
init_vp9(my_vpx_cfg_t * my_cfg)1542 static void init_vp9(my_vpx_cfg_t *my_cfg)
1543 {
1544 vpx_codec_enc_config_default(vpx_codec_vp9_cx(), &my_cfg->enc_cfg, 0);
1545
1546 my_cfg->dec_cfg.threads = vpx_globals.dec_threads;
1547 my_cfg->enc_cfg.g_threads = vpx_globals.enc_threads;
1548 my_cfg->static_thresh = 1000;
1549
1550 my_cfg->cpuused = -8;
1551 my_cfg->enc_cfg.g_profile = 0;
1552 my_cfg->enc_cfg.g_lag_in_frames = 0;
1553 my_cfg->enc_cfg.g_timebase.den = 1000;
1554 my_cfg->enc_cfg.g_error_resilient = VPX_ERROR_RESILIENT_PARTITIONS;
1555 my_cfg->enc_cfg.rc_resize_allowed = 1;
1556 my_cfg->enc_cfg.rc_end_usage = VPX_CBR;
1557 my_cfg->enc_cfg.rc_target_bitrate = switch_parse_bandwidth_string("1mb");
1558 my_cfg->enc_cfg.rc_min_quantizer = 4;
1559 my_cfg->enc_cfg.rc_max_quantizer = 63;
1560 my_cfg->enc_cfg.rc_overshoot_pct = 50;
1561 my_cfg->enc_cfg.rc_buf_sz = 5000;
1562 my_cfg->enc_cfg.rc_buf_initial_sz = 1000;
1563 my_cfg->enc_cfg.rc_buf_optimal_sz = 1000;
1564 my_cfg->enc_cfg.kf_max_dist = 360;
1565 my_cfg->tune_content = VP9E_CONTENT_SCREEN;
1566 }
1567
find_cfg_profile(const char * name,switch_bool_t reconfig)1568 static my_vpx_cfg_t *find_cfg_profile(const char *name, switch_bool_t reconfig)
1569 {
1570 int i;
1571
1572 for (i = 0; i < MAX_PROFILES; i++) {
1573 if (!vpx_globals.profiles[i]) {
1574 vpx_globals.profiles[i] = malloc(sizeof(my_vpx_cfg_t));
1575 switch_assert(vpx_globals.profiles[i]);
1576 memset(vpx_globals.profiles[i], 0, sizeof(my_vpx_cfg_t));
1577 switch_set_string(vpx_globals.profiles[i]->name, name);
1578
1579 if (!strcmp(name, "vp9")) {
1580 init_vp9(vpx_globals.profiles[i]);
1581 } else {
1582 init_vp8(vpx_globals.profiles[i]);
1583 }
1584
1585 vpx_globals.profiles[i]->token_parts = switch_core_cpu_count() > 1 ? 3 : 0;
1586
1587 return vpx_globals.profiles[i];
1588 }
1589
1590 if (!strcmp(name, vpx_globals.profiles[i]->name)) {
1591 if (reconfig) {
1592 memset(vpx_globals.profiles[i], 0, sizeof(my_vpx_cfg_t));
1593 switch_set_string(vpx_globals.profiles[i]->name, name);
1594 }
1595
1596 return vpx_globals.profiles[i];
1597 }
1598 }
1599
1600 return NULL;
1601 }
1602
1603 #define UINTVAL(v) (v > 0 ? v : 0);
1604 #define _VPX_CHECK_ERR(fmt, ...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "VPX config param \"%s\" -> \"%s\" value \"%s\" " fmt "\n", profile_name, name, value, __VA_ARGS__)
1605 #define _VPX_CHECK_ERRDEF(var, fmt, ...) _VPX_CHECK_ERR(fmt ", leave default %d", __VA_ARGS__, var)
1606 #define _VPX_CHECK_ERRDEF_INVL(var) _VPX_CHECK_ERRDEF(var, "%s", "is invalid")
1607 #define _VPX_CHECK_ERRDEF_NOTAPPL(var) _VPX_CHECK_ERRDEF(var, "%s", "is not applicable")
1608 #define _VPX_CHECK_MIN(var, val, min) do { int lval = val; if (lval < (min)) _VPX_CHECK_ERRDEF(var, "is lower than %d", min); else var = lval; } while(0)
1609 #define _VPX_CHECK_MAX(var, val, max) do { int lval = val; if (lval > (max)) _VPX_CHECK_ERRDEF(var, "is larger than %d", max); else var = lval; } while(0)
1610 #define _VPX_CHECK_MIN_MAX(var, val, min, max) do { int lval = val; if ((lval < (min)) || (lval > (max))) _VPX_CHECK_ERRDEF(var, "not in [%d..%d]", min, max); else var = lval; } while(0)
1611
parse_profile(my_vpx_cfg_t * my_cfg,switch_xml_t profile,int codec_type)1612 static void parse_profile(my_vpx_cfg_t *my_cfg, switch_xml_t profile, int codec_type)
1613 {
1614 switch_xml_t param = NULL;
1615 const char *profile_name = profile->name;
1616
1617 vpx_codec_dec_cfg_t *dec_cfg = NULL;
1618 vpx_codec_enc_cfg_t *enc_cfg = NULL;
1619
1620 dec_cfg = &my_cfg->dec_cfg;
1621 enc_cfg = &my_cfg->enc_cfg;
1622
1623 for (param = switch_xml_child(profile, "param"); param; param = param->next) {
1624 const char *name = switch_xml_attr(param, "name");
1625 const char *value = switch_xml_attr(param, "value");
1626 int val;
1627
1628 if (!enc_cfg || !dec_cfg) break;
1629 if (zstr(name) || zstr(value)) continue;
1630
1631 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s: %s = %s\n", my_cfg->name, name, value);
1632
1633 val = atoi(value);
1634
1635 if (!strcmp(name, "dec-threads")) {
1636 _VPX_CHECK_MIN(dec_cfg->threads, switch_parse_cpu_string(value), 1);
1637 } else if (!strcmp(name, "enc-threads")) {
1638 _VPX_CHECK_MIN(enc_cfg->g_threads, switch_parse_cpu_string(value), 1);
1639 } else if (!strcmp(name, "g-profile")) {
1640 _VPX_CHECK_MIN_MAX(enc_cfg->g_profile, val, 0, 3);
1641 #if 0
1642 } else if (!strcmp(name, "g-timebase")) {
1643 int num = 0;
1644 int den = 0;
1645 char *slash = strchr(value, '/');
1646
1647 num = UINTVAL(val);
1648
1649 if (slash) {
1650 slash++;
1651 den = atoi(slash);
1652
1653 if (den < 0) den = 0;
1654 }
1655
1656 if (num && den) {
1657 enc_cfg->g_timebase.num = num;
1658 enc_cfg->g_timebase.den = den;
1659 }
1660 #endif
1661 } else if (!strcmp(name, "g-error-resilient")) {
1662 char *s = strdup(value);
1663 if (s) {
1664 vpx_codec_er_flags_t res = 0;
1665 int argc;
1666 char *argv[10];
1667 int i;
1668
1669 argc = switch_separate_string(s, '|', argv, (sizeof(argv) / sizeof(argv[0])));
1670 for (i = 0; i < argc; i++) {
1671 if (!strcasecmp(argv[i], "DEFAULT")) {
1672 res |= VPX_ERROR_RESILIENT_DEFAULT;
1673 } else if (!strcasecmp(argv[i], "PARTITIONS")) {
1674 res |= VPX_ERROR_RESILIENT_PARTITIONS;
1675 } else {
1676 _VPX_CHECK_ERR("has invalid token \"%s\"", argv[i]);
1677 }
1678 }
1679
1680 free(s);
1681 enc_cfg->g_error_resilient = res;
1682 }
1683 } else if (!strcmp(name, "g-pass")) {
1684 if (!strcasecmp(value, "ONE_PASS")) {
1685 enc_cfg->g_pass = VPX_RC_ONE_PASS;
1686 } else if (!strcasecmp(value, "FIRST_PASS")) {
1687 enc_cfg->g_pass = VPX_RC_FIRST_PASS;
1688 } else if (!strcasecmp(value, "LAST_PASS")) {
1689 enc_cfg->g_pass = VPX_RC_FIRST_PASS;
1690 } else {
1691 _VPX_CHECK_ERRDEF_INVL(enc_cfg->g_pass);
1692 }
1693 } else if (!strcmp(name, "g-lag-in-frames")) {
1694 _VPX_CHECK_MIN_MAX(enc_cfg->g_lag_in_frames, val, 0, 25);
1695 } else if (!strcmp(name, "rc_dropframe_thresh")) {
1696 _VPX_CHECK_MIN_MAX(enc_cfg->rc_dropframe_thresh, val, 0, 100);
1697 } else if (!strcmp(name, "rc-resize-allowed")) {
1698 _VPX_CHECK_MIN_MAX(enc_cfg->rc_resize_allowed, val, 0, 1);
1699 } else if (!strcmp(name, "rc-scaled-width")) {
1700 _VPX_CHECK_MIN(enc_cfg->rc_scaled_width, val, 0);
1701 } else if (!strcmp(name, "rc-scaled-height")) {
1702 _VPX_CHECK_MIN(enc_cfg->rc_scaled_height, val, 0);
1703 } else if (!strcmp(name, "rc-resize-up-thresh")) {
1704 _VPX_CHECK_MIN_MAX(enc_cfg->rc_resize_up_thresh, val, 0, 100);
1705 } else if (!strcmp(name, "rc-resize-down-thresh")) {
1706 _VPX_CHECK_MIN_MAX(enc_cfg->rc_resize_down_thresh, val, 0, 100);
1707 } else if (!strcmp(name, "rc-end-usage")) {
1708 if (!strcasecmp(value, "VBR")) {
1709 enc_cfg->rc_end_usage = VPX_VBR;
1710 } else if (!strcasecmp(value, "CBR")) {
1711 enc_cfg->rc_end_usage = VPX_CBR;
1712 } else if (!strcasecmp(value, "CQ")) {
1713 enc_cfg->rc_end_usage = VPX_CQ;
1714 } else if (!strcasecmp(value, "Q")) {
1715 enc_cfg->rc_end_usage = VPX_Q;
1716 } else {
1717 _VPX_CHECK_ERRDEF_INVL(enc_cfg->rc_end_usage);
1718 }
1719 } else if (!strcmp(name, "rc-target-bitrate")) {
1720 _VPX_CHECK_MIN(enc_cfg->rc_target_bitrate, switch_parse_bandwidth_string(value), 1);
1721 } else if (!strcmp(name, "rc-min-quantizer")) {
1722 _VPX_CHECK_MIN_MAX(enc_cfg->rc_min_quantizer, val, 0, 63);
1723 } else if (!strcmp(name, "rc-max-quantizer")) {
1724 _VPX_CHECK_MIN_MAX(enc_cfg->rc_max_quantizer, val, 0, 63);
1725 } else if (!strcmp(name, "rc-undershoot-pct")) {
1726 if (codec_type == CODEC_TYPE_VP9) {
1727 _VPX_CHECK_MIN_MAX(enc_cfg->rc_undershoot_pct, val, 0, 100);
1728 } else {
1729 _VPX_CHECK_MIN_MAX(enc_cfg->rc_undershoot_pct, val, 0, 1000);
1730 }
1731 } else if (!strcmp(name, "rc-overshoot-pct")) {
1732 if (codec_type == CODEC_TYPE_VP9) {
1733 _VPX_CHECK_MIN_MAX(enc_cfg->rc_overshoot_pct, val, 0, 100);
1734 } else {
1735 _VPX_CHECK_MIN_MAX(enc_cfg->rc_overshoot_pct, val, 0, 1000);
1736 }
1737 } else if (!strcmp(name, "rc-buf-sz")) {
1738 _VPX_CHECK_MIN(enc_cfg->rc_buf_sz, val, 1);
1739 } else if (!strcmp(name, "rc-buf-initial-sz")) {
1740 _VPX_CHECK_MIN(enc_cfg->rc_buf_initial_sz, val, 1);
1741 } else if (!strcmp(name, "rc-buf-optimal-sz")) {
1742 _VPX_CHECK_MIN(enc_cfg->rc_buf_optimal_sz, val, 1);
1743 } else if (!strcmp(name, "rc-2pass-vbr-bias-pct")) {
1744 _VPX_CHECK_MIN_MAX(enc_cfg->rc_2pass_vbr_bias_pct, val, 0, 100);
1745 } else if (!strcmp(name, "rc-2pass-vbr-minsection-pct")) {
1746 _VPX_CHECK_MIN(enc_cfg->rc_2pass_vbr_minsection_pct, val, 1);
1747 } else if (!strcmp(name, "rc-2pass-vbr-maxsection-pct")) {
1748 _VPX_CHECK_MIN(enc_cfg->rc_2pass_vbr_maxsection_pct, val, 1);
1749 } else if (!strcmp(name, "kf-mode")) {
1750 if (!strcasecmp(value, "AUTO")) {
1751 enc_cfg->kf_mode = VPX_KF_AUTO;
1752 } else if (!strcasecmp(value, "DISABLED")) {
1753 enc_cfg->kf_mode = VPX_KF_DISABLED;
1754 } else {
1755 _VPX_CHECK_ERRDEF_INVL(enc_cfg->kf_mode);
1756 }
1757 } else if (!strcmp(name, "kf-min-dist")) {
1758 _VPX_CHECK_MIN(enc_cfg->kf_min_dist, val, 0);
1759 } else if (!strcmp(name, "kf-max-dist")) {
1760 _VPX_CHECK_MIN(enc_cfg->kf_max_dist, val, 0);
1761 } else if (!strcmp(name, "ss-number-layers")) {
1762 _VPX_CHECK_MIN_MAX(enc_cfg->ss_number_layers, val, 0, VPX_SS_MAX_LAYERS);
1763 } else if (!strcmp(name, "ts-number-layers")) {
1764 if (codec_type == CODEC_TYPE_VP8) {
1765 _VPX_CHECK_MIN_MAX(enc_cfg->ts_number_layers, val, 0, VPX_SS_MAX_LAYERS);
1766 } else if (codec_type == CODEC_TYPE_VP9) {
1767 _VPX_CHECK_MIN_MAX(enc_cfg->ts_number_layers, val, enc_cfg->ts_number_layers, enc_cfg->ts_number_layers); // lock it
1768 } else {
1769 _VPX_CHECK_ERRDEF_NOTAPPL(enc_cfg->ts_number_layers);
1770 }
1771 } else if (!strcmp(name, "ts-periodicity")) {
1772 if (codec_type == CODEC_TYPE_VP9) {
1773 _VPX_CHECK_MIN_MAX(enc_cfg->ts_periodicity, val, enc_cfg->ts_periodicity, enc_cfg->ts_periodicity); // lock it
1774 } else {
1775 _VPX_CHECK_MIN_MAX(enc_cfg->ts_periodicity, val, 0, 16);
1776 }
1777 } else if (!strcmp(name, "temporal-layering-mode")) {
1778 if (codec_type == CODEC_TYPE_VP9) {
1779 _VPX_CHECK_MIN_MAX(enc_cfg->temporal_layering_mode, val, enc_cfg->temporal_layering_mode, enc_cfg->temporal_layering_mode); // lock it
1780 } else {
1781 _VPX_CHECK_MIN_MAX(enc_cfg->temporal_layering_mode, val, 0, 3);
1782 }
1783 } else if (!strcmp(name, "lossless")) {
1784 if (codec_type == CODEC_TYPE_VP9) {
1785 _VPX_CHECK_MIN_MAX(my_cfg->lossless, val, 0, 1);
1786 } else {
1787 _VPX_CHECK_ERRDEF_NOTAPPL(my_cfg->lossless);
1788 }
1789 } else if (!strcmp(name, "cpuused")) {
1790 if (codec_type == CODEC_TYPE_VP8) {
1791 _VPX_CHECK_MIN_MAX(my_cfg->cpuused, val, -16, 16);
1792 } else {
1793 _VPX_CHECK_MIN_MAX(my_cfg->cpuused, val, -8, 8);
1794 }
1795 } else if (!strcmp(name, "token-parts")) {
1796 _VPX_CHECK_MIN_MAX(my_cfg->token_parts, switch_parse_cpu_string(value), VP8_ONE_TOKENPARTITION, VP8_EIGHT_TOKENPARTITION);
1797 } else if (!strcmp(name, "static-thresh")) {
1798 _VPX_CHECK_MIN(my_cfg->static_thresh, val, 0);
1799 } else if (!strcmp(name, "noise-sensitivity")) {
1800 if (codec_type == CODEC_TYPE_VP8) {
1801 _VPX_CHECK_MIN_MAX(my_cfg->noise_sensitivity, val, 0, 6);
1802 } else {
1803 _VPX_CHECK_ERRDEF_NOTAPPL(my_cfg->noise_sensitivity);
1804 }
1805 } else if (!strcmp(name, "max-intra-bitrate-pct")) {
1806 if (codec_type == CODEC_TYPE_VP8) {
1807 _VPX_CHECK_MIN(my_cfg->max_intra_bitrate_pct, val, 0);
1808 } else {
1809 _VPX_CHECK_ERRDEF_NOTAPPL(my_cfg->max_intra_bitrate_pct);
1810 }
1811 } else if (!strcmp(name, "vp9e-tune-content")) {
1812 if (codec_type == CODEC_TYPE_VP9) {
1813 if (!strcasecmp(value, "DEFAULT")) {
1814 my_cfg->tune_content = VP9E_CONTENT_DEFAULT;
1815 } else if (!strcasecmp(value, "SCREEN")) {
1816 my_cfg->tune_content = VP9E_CONTENT_SCREEN;
1817 } else {
1818 _VPX_CHECK_ERRDEF_INVL(my_cfg->tune_content);
1819 }
1820 } else {
1821 _VPX_CHECK_ERRDEF_NOTAPPL(my_cfg->tune_content);
1822 }
1823 }
1824 } // for param
1825 }
1826
parse_codecs(my_vpx_cfg_t * my_cfg,switch_xml_t codecs)1827 static void parse_codecs(my_vpx_cfg_t *my_cfg, switch_xml_t codecs)
1828 {
1829 switch_xml_t codec = NULL;
1830
1831 if (!codecs) {
1832 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no codecs in %s\n", my_cfg->name);
1833 return;
1834 }
1835
1836 codec = switch_xml_child(codecs, "codec");
1837
1838 if (my_cfg->codecs) {
1839 switch_event_destroy(&my_cfg->codecs);
1840 }
1841
1842 switch_event_create(&my_cfg->codecs, SWITCH_EVENT_CLONE);
1843
1844 for (; codec; codec = codec->next) {
1845 const char *name = switch_xml_attr(codec, "name");
1846 const char *profile = switch_xml_attr(codec, "profile");
1847
1848 if (zstr(name) || zstr(profile)) continue;
1849
1850 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "codec: %s, profile: %s\n", name, profile);
1851
1852 switch_event_add_header_string(my_cfg->codecs, SWITCH_STACK_BOTTOM, name, profile);
1853 }
1854 }
1855
load_config()1856 static void load_config()
1857 {
1858 switch_xml_t cfg = NULL, xml = NULL;
1859 my_vpx_cfg_t *my_cfg = NULL;
1860
1861 memset(&vpx_globals, 0, sizeof(vpx_globals));
1862
1863 vpx_globals.max_bitrate = switch_calc_bitrate(1920, 1080, 5, 60);
1864 vpx_globals.rtp_slice_size = SLICE_SIZE;
1865 vpx_globals.key_frame_min_freq = KEY_FRAME_MIN_FREQ;
1866
1867 xml = switch_xml_open_cfg("vpx.conf", &cfg, NULL);
1868
1869 if (xml) {
1870 switch_xml_t settings = switch_xml_child(cfg, "settings");
1871 switch_xml_t profiles = switch_xml_child(cfg, "profiles");
1872
1873 if (settings) {
1874 switch_xml_t param;
1875
1876 for (param = switch_xml_child(settings, "param"); param; param = param->next) {
1877 const char *profile_name = "settings"; // for _VPX_CHECK_*() macroses only
1878 const char *name = switch_xml_attr(param, "name");
1879 const char *value = switch_xml_attr(param, "value");
1880
1881 if (zstr(name) || zstr(value)) continue;
1882
1883 if (!strcmp(name, "debug")) {
1884 vpx_globals.debug = atoi(value);
1885 } else if (!strcmp(name, "max-bitrate")) {
1886 _VPX_CHECK_MIN(vpx_globals.max_bitrate, switch_parse_bandwidth_string(value), 1);
1887 } else if (!strcmp(name, "rtp-slice-size")) {
1888 _VPX_CHECK_MIN_MAX(vpx_globals.rtp_slice_size, atoi(value), 500, 1500);
1889 } else if (!strcmp(name, "key-frame-min-freq")) {
1890 _VPX_CHECK_MIN_MAX(vpx_globals.key_frame_min_freq, atoi(value) * 1000, 10 * 1000, 3000 * 1000);
1891 } else if (!strcmp(name, "dec-threads")) {
1892 int val = switch_parse_cpu_string(value);
1893 _VPX_CHECK_MIN(vpx_globals.dec_threads, val, 1);
1894 } else if (!strcmp(name, "enc-threads")) {
1895 int val = switch_parse_cpu_string(value);
1896 _VPX_CHECK_MIN(vpx_globals.enc_threads, val, 1);
1897 }
1898 }
1899 }
1900
1901 if (profiles) {
1902 switch_xml_t profile = switch_xml_child(profiles, "profile");
1903
1904 for (; profile; profile = profile->next) {
1905 switch_xml_t codecs = switch_xml_child(profile, "codecs");
1906 const char *profile_name = switch_xml_attr(profile, "name");
1907 my_vpx_cfg_t *my_cfg = NULL;
1908
1909 if (zstr(profile_name)) continue;
1910
1911 my_cfg = find_cfg_profile(profile_name, SWITCH_TRUE);
1912
1913 if (!my_cfg) continue;
1914
1915 parse_profile(my_cfg, profile, CODEC_TYPE(profile_name));
1916 parse_codecs(my_cfg, codecs);
1917 } // for profile
1918 } // profiles
1919
1920 switch_xml_free(xml);
1921 } // xml
1922
1923 if (vpx_globals.max_bitrate <= 0) {
1924 vpx_globals.max_bitrate = switch_calc_bitrate(1920, 1080, 5, 60);
1925 }
1926
1927 if (vpx_globals.rtp_slice_size < 500 || vpx_globals.rtp_slice_size > 1500) {
1928 vpx_globals.rtp_slice_size = SLICE_SIZE;
1929 }
1930
1931 if (vpx_globals.key_frame_min_freq < 10000 || vpx_globals.key_frame_min_freq > 3 * 1000000) {
1932 vpx_globals.key_frame_min_freq = KEY_FRAME_MIN_FREQ;
1933 }
1934
1935 my_cfg = find_cfg_profile("vp8", SWITCH_FALSE);
1936
1937 if (my_cfg) {
1938 if (!my_cfg->enc_cfg.g_threads) my_cfg->enc_cfg.g_threads = 1;
1939 if (!my_cfg->dec_cfg.threads) my_cfg->dec_cfg.threads = switch_parse_cpu_string("cpu/2/4");
1940 }
1941
1942 my_cfg = find_cfg_profile("vp9", SWITCH_FALSE);
1943
1944 if (my_cfg) {
1945 if (!my_cfg->enc_cfg.g_threads) my_cfg->enc_cfg.g_threads = 1;
1946 if (!my_cfg->dec_cfg.threads) my_cfg->dec_cfg.threads = switch_parse_cpu_string("cpu/2/4");
1947 }
1948 }
1949
1950 #define VPX_API_SYNTAX "<reload|debug <on|off>>"
SWITCH_STANDARD_API(vpx_api_function)1951 SWITCH_STANDARD_API(vpx_api_function)
1952 {
1953 if (session) {
1954 return SWITCH_STATUS_FALSE;
1955 }
1956
1957 if (zstr(cmd)) {
1958 goto usage;
1959 }
1960
1961 if (!strcasecmp(cmd, "reload")) {
1962 const char *err;
1963 my_vpx_cfg_t *my_cfg;
1964 int i;
1965
1966 switch_xml_reload(&err);
1967 stream->write_function(stream, "Reload XML [%s]\n", err);
1968
1969 load_config();
1970
1971 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " %-26s = %d\n", "rtp-slice-size", vpx_globals.rtp_slice_size);
1972 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " %-26s = %d\n", "key-frame-min-freq", vpx_globals.key_frame_min_freq);
1973
1974 for (i = 0; i < MAX_PROFILES; i++) {
1975 my_cfg = vpx_globals.profiles[i];
1976
1977 if (!my_cfg) break;
1978
1979 if (!strcmp(my_cfg->name, "vp8")) {
1980 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Codec: %s\n", vpx_codec_iface_name(vpx_codec_vp8_cx()));
1981 } else if (!strcmp(my_cfg->name, "vp9")) {
1982 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Codec: %s\n", vpx_codec_iface_name(vpx_codec_vp9_cx()));
1983 } else {
1984 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Codec: %s\n", my_cfg->name);
1985 }
1986
1987 show_config(my_cfg, &my_cfg->enc_cfg);
1988 }
1989
1990 stream->write_function(stream, "+OK\n");
1991 } else if (!strcasecmp(cmd, "debug")) {
1992 stream->write_function(stream, "+OK debug %s\n", vpx_globals.debug ? "on" : "off");
1993 } else if (!strcasecmp(cmd, "debug on")) {
1994 vpx_globals.debug = 1;
1995 stream->write_function(stream, "+OK debug on\n");
1996 } else if (!strcasecmp(cmd, "debug off")) {
1997 vpx_globals.debug = 0;
1998 stream->write_function(stream, "+OK debug off\n");
1999 }
2000
2001 return SWITCH_STATUS_SUCCESS;
2002
2003 usage:
2004 stream->write_function(stream, "USAGE: %s\n", VPX_API_SYNTAX);
2005 return SWITCH_STATUS_SUCCESS;
2006 }
2007
SWITCH_MODULE_LOAD_FUNCTION(mod_vpx_load)2008 SWITCH_MODULE_LOAD_FUNCTION(mod_vpx_load)
2009 {
2010 switch_codec_interface_t *codec_interface;
2011 switch_api_interface_t *vpx_api_interface;
2012
2013 memset(&vpx_globals, 0, sizeof(struct vpx_globals));
2014 load_config();
2015
2016 /* connect my internal structure to the blank pointer passed to me */
2017 *module_interface = switch_loadable_module_create_module_interface(pool, modname);
2018
2019 SWITCH_ADD_CODEC(codec_interface, "VP8 Video");
2020 switch_core_codec_add_video_implementation(pool, codec_interface, 99, "VP8", NULL,
2021 switch_vpx_init, switch_vpx_encode, switch_vpx_decode, switch_vpx_control, switch_vpx_destroy);
2022 SWITCH_ADD_CODEC(codec_interface, "VP9 Video");
2023 switch_core_codec_add_video_implementation(pool, codec_interface, 99, "VP9", NULL,
2024 switch_vpx_init, switch_vpx_encode, switch_vpx_decode, switch_vpx_control, switch_vpx_destroy);
2025
2026 SWITCH_ADD_API(vpx_api_interface, "vpx",
2027 "VPX API", vpx_api_function, VPX_API_SYNTAX);
2028
2029 switch_console_set_complete("add vpx reload");
2030 switch_console_set_complete("add vpx debug");
2031 switch_console_set_complete("add vpx debug on");
2032 switch_console_set_complete("add vpx debug off");
2033
2034 /* indicate that the module should continue to be loaded */
2035 return SWITCH_STATUS_SUCCESS;
2036 }
2037
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_vpx_shutdown)2038 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_vpx_shutdown)
2039 {
2040 int i;
2041
2042 for (i = 0; i < MAX_PROFILES; i++) {
2043 my_vpx_cfg_t *my_cfg = vpx_globals.profiles[i];
2044
2045 if (!my_cfg) break;
2046
2047 if (my_cfg->codecs) {
2048 switch_event_destroy(&my_cfg->codecs);
2049 }
2050
2051 free(my_cfg);
2052 }
2053
2054 return SWITCH_STATUS_SUCCESS;
2055 }
2056 #endif
2057 #endif
2058 /* For Emacs:
2059 * Local Variables:
2060 * mode:c
2061 * indent-tabs-mode:t
2062 * tab-width:4
2063 * c-basic-offset:4
2064 * End:
2065 * For VIM:
2066 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
2067 */
2068