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> 46 #define VPX_SWITCH_LOG_LEVEL SWITCH_LOG_ERROR 48 #define VPX_SWITCH_LOG_LEVEL SWITCH_LOG_DEBUG1 51 #define SLICE_SIZE SWITCH_DEFAULT_VIDEO_SIZE 52 #define KEY_FRAME_MIN_FREQ 250000 54 #define CODEC_TYPE_ANY 0 55 #define CODEC_TYPE_VP8 8 56 #define CODEC_TYPE_VP9 9 58 typedef struct my_vpx_cfg_s {
64 int noise_sensitivity;
65 int max_intra_bitrate_pct;
66 vp9e_tune_content tune_content;
68 vpx_codec_enc_cfg_t enc_cfg;
69 vpx_codec_dec_cfg_t dec_cfg;
73 #define SHOW(cfg, field) switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO, " %-28s = %d\n", #field, cfg->field) 75 static void show_config(my_vpx_cfg_t *my_cfg, vpx_codec_enc_cfg_t *cfg)
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);
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);
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);
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);
126 if (my_cfg->codecs) {
131 for (hp = my_cfg->codecs->headers; hp; hp = hp->
next) {
178 #pragma pack(push, r1, 1) 181 #if SWITCH_BYTE_ORDER == __BIG_ENDIAN 185 unsigned reserved1:1;
186 unsigned non_referenced:1;
188 unsigned reserved2:1;
197 unsigned TL0PICIDX:8;
201 } vp8_payload_descriptor_t;
205 unsigned have_p_layer:1;
206 unsigned have_layer_ind:1;
207 unsigned is_flexible:1;
212 } vp9_payload_descriptor_t;
229 unsigned temporal_id:3;
230 unsigned temporal_up_switch:1;
231 unsigned spatial_id:3;
232 unsigned inter_layer_predicted:1;
239 unsigned reserved2:1;
241 unsigned non_referenced:1;
242 unsigned reserved1:1;
251 unsigned TL0PICIDX:8;
255 } vp8_payload_descriptor_t;
262 unsigned is_flexible:1;
263 unsigned have_layer_ind:1;
264 unsigned have_p_layer:1;
266 } vp9_payload_descriptor_t;
283 unsigned inter_layer_predicted:1;
284 unsigned spatial_id:3;
285 unsigned temporal_up_switch:1;
286 unsigned temporal_id:3;
292 vp8_payload_descriptor_t vp8;
293 vp9_payload_descriptor_t vp9;
294 } vpx_payload_descriptor_t;
296 #define kMaxVp9NumberOfSpatialLayers 16 300 uint8_t picture_id_sli;
302 uint64_t picture_id_rpsi;
311 uint8_t temporal_idx;
319 size_t num_spatial_layers;
321 uint16_t width[kMaxVp9NumberOfSpatialLayers];
322 uint16_t height[kMaxVp9NumberOfSpatialLayers];
328 #pragma pack(pop, r1) 332 #define __IS_VP8_KEY_FRAME(byte) !(((byte) & 0x01)) 333 static inline int IS_VP8_KEY_FRAME(uint8_t *data)
348 uint8_t M = (*data) & 0x80;
352 if (X & 0x40) data++;
353 if (X & 0x30) data++;
356 if (S && (PID == 0)) {
357 return __IS_VP8_KEY_FRAME(*data);
364 #define IS_VP9_KEY_FRAME(byte) ((((byte) & 0x40) == 0) && ((byte) & 0x0A)) 365 #define IS_VP9_START_PKT(byte) ((byte) & 0x08) 368 #undef SWITCH_MOD_DECLARE_DATA 369 #define SWITCH_MOD_DECLARE_DATA __declspec(dllexport) 380 vpx_codec_iface_t *encoder_interface;
381 vpx_codec_iface_t *decoder_interface;
384 unsigned int bandwidth;
385 vpx_codec_enc_cfg_t config;
388 vpx_codec_ctx_t encoder;
389 uint8_t encoder_init;
397 const vpx_codec_cx_pkt_t *pkt;
398 vpx_codec_iter_t enc_iter;
399 vpx_codec_iter_t dec_iter;
402 vpx_codec_ctx_t decoder;
403 uint8_t decoder_init;
404 int decoded_first_frame;
409 uint32_t last_received_timestamp;
411 uint16_t last_received_seq;
413 int need_encoder_reset;
414 int need_decoder_reset;
415 int32_t change_bandwidth;
423 typedef struct vpx_context vpx_context_t;
425 #define MAX_PROFILES 100 429 uint32_t max_bitrate;
430 uint32_t rtp_slice_size;
431 uint32_t key_frame_min_freq;
433 uint32_t dec_threads;
434 uint32_t enc_threads;
436 my_vpx_cfg_t *profiles[MAX_PROFILES];
439 struct vpx_globals vpx_globals = { 0 };
442 static void parse_profile(my_vpx_cfg_t *my_cfg,
switch_xml_t profile,
int codec_type);
446 vpx_context_t *context = (vpx_context_t *)codec->
private_info;
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;
460 if (context->is_vp9) {
468 cfg.threads = my_cfg->dec_cfg.threads;
470 if ((err = vpx_codec_dec_init(&context->decoder, context->decoder_interface, &cfg, dec_flags)) != VPX_CODEC_OK) {
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));
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;
487 ppcfg.post_proc_flag = VP8_DEBLOCK;
489 ppcfg.deblocking_level = 1;
491 vpx_codec_control(&context->decoder, VP8_SET_POSTPROC, &ppcfg);
493 if (context->vpx_packet_buffer) {
503 static int CODEC_TYPE(
const char *
string)
505 if (!strcmp(
string,
"vp8")) {
506 return CODEC_TYPE_VP8;
507 }
else if (!strcmp(
string,
"vp9")) {
508 return CODEC_TYPE_VP9;
511 return CODEC_TYPE_ANY;
514 static void parse_codec_specific_profile(my_vpx_cfg_t *my_cfg,
const char *codec_name)
524 for (hp = my_cfg->codecs->headers; hp; hp = hp->
next) {
526 if (!strcmp(hp->
name, codec_name)) {
531 if (!strcmp(hp->
value, name)) {
532 parse_profile(my_cfg, profile, CODEC_TYPE(codec_name));
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;
548 char *codec_name =
"vp8";
550 if (context->is_vp9) {
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);
566 if (context->is_vp9) {
567 my_cfg->enc_cfg.g_profile = 0;
570 if (my_cfg->codecs) {
571 parse_codec_specific_profile(my_cfg, codec_name);
574 if (vpx_globals.debug) show_config(my_cfg, &my_cfg->enc_cfg);
576 if (!context->codec_settings.video.width) {
577 context->codec_settings.video.width = 1280;
580 if (!context->codec_settings.video.height) {
581 context->codec_settings.video.height = 720;
584 if (context->codec_settings.video.bandwidth == -1) {
585 context->codec_settings.video.bandwidth = 0;
588 if (context->codec_settings.video.bandwidth) {
589 context->bandwidth = context->codec_settings.video.bandwidth;
591 context->bandwidth =
switch_calc_bitrate(context->codec_settings.video.width, context->codec_settings.video.height, 1, 15);
594 if (context->bandwidth > vpx_globals.max_bitrate) {
596 context->bandwidth = vpx_globals.max_bitrate;
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);
607 *config = my_cfg->enc_cfg;
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;
613 if (context->is_vp9) {
614 if (my_cfg->lossless) {
615 config->rc_min_quantizer = 0;
616 config->rc_max_quantizer = 0;
620 if (context->encoder_init) {
621 if ((err = vpx_codec_enc_config_set(&context->encoder, config)) != VPX_CODEC_OK) {
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));
629 if (vpx_globals.debug) {
631 show_config(my_cfg, config);
634 if ((err = vpx_codec_enc_init(&context->encoder, context->encoder_interface, config, 0 & VPX_CODEC_USE_OUTPUT_PARTITION)) != VPX_CODEC_OK) {
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));
642 context->encoder_init = 1;
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);
648 if (context->is_vp9) {
649 if (my_cfg->lossless) {
650 vpx_codec_control(&context->encoder, VP9E_SET_LOSSLESS, 1);
653 vpx_codec_control(&context->encoder, VP9E_SET_TUNE_CONTENT, my_cfg->tune_content);
655 vpx_codec_control(&context->encoder, VP8E_SET_NOISE_SENSITIVITY, my_cfg->noise_sensitivity);
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);
668 vpx_context_t *context = NULL;
669 int encoding, decoding;
678 memset(context, 0,
sizeof(*context));
679 context->flags = flags;
683 if (codec_settings) {
684 context->codec_settings = *codec_settings;
689 context->encoder_interface = vpx_codec_vp9_cx();
690 context->decoder_interface = vpx_codec_vp9_dx();
692 context->encoder_interface = vpx_codec_vp8_cx();
693 context->decoder_interface = vpx_codec_vp8_dx();
700 context->codec_settings.video.width = 320;
701 context->codec_settings.video.height = 240;
706 if (!context->is_vp9) {
707 context->picture_id = 13;
709 context->vp9.picture_id = 13;
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;
724 if ((context->pkt = vpx_codec_get_cx_data(&context->encoder, &context->enc_iter))) {
726 if (!context->pbuffer) {
734 if (context->pbuffer) {
738 if (!context->pkt || context->pkt->kind != VPX_CODEC_CX_FRAME_PKT || !remaining_bytes) {
746 key = (context->pkt->data.frame.flags & VPX_FRAME_IS_KEY);
750 context->pkt->data.frame.flags, context->pkt->data.frame.pts, context->pkt->data.frame.duration, context->pkt->data.frame.partition_id);
754 *(uint8_t *)frame->
data = 0;
755 payload_descriptor = (vpx_payload_descriptor_t *) frame->
data;
756 memset(payload_descriptor, 0,
sizeof(*payload_descriptor));
759 if (context->is_vp9) {
765 body = ((uint8_t *)frame->
data) + hdrlen;
767 if (context->is_vp9) {
768 payload_descriptor->vp9.start = start;
772 payload_descriptor->vp9.have_pid = 1;
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;
780 *body++ = context->vp9.picture_id;
786 vp9_ss_t *ss = (vp9_ss_t *)body;
788 payload_descriptor->vp9.have_ss = 1;
789 payload_descriptor->vp9.have_p_layer = 0;
803 w = (uint16_t *)body;
805 h = (uint16_t *)body;
808 *w = (uint16_t)context->codec_settings.video.width;
809 *h = (uint16_t)context->codec_settings.video.height;
811 hdrlen += (ss->n_s + 1) * 4;
814 payload_descriptor->vp9.have_p_layer = 1;
819 if (!context->is_vp9) {
820 payload_descriptor->vp8.start = start;
822 payload_descriptor->vp8.extended = 1;
824 payload_descriptor->vp8.I = 1;
826 payload_descriptor->vp8.M = 1;
827 c = ((uint8_t *)frame->
data) + 2;
828 *c++ = (context->picture_id >> 8) | 0x80;
829 *c = context->picture_id & 0xff;
831 payload_descriptor->vp8.L = 0;
832 payload_descriptor->vp8.TL0PICIDX = 0;
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;
848 max_payload_size = vpx_globals.rtp_slice_size - hdrlen;
849 payload_size = remaining_bytes / ((remaining_bytes + max_payload_size - 1) / max_payload_size);
851 if (remaining_bytes <= payload_size) {
854 frame->
datalen = hdrlen + remaining_bytes;
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;
864 context->picture_id++;
865 if ((uint16_t)context->picture_id > 0x7fff) {
866 context->picture_id = 0;
873 frame->
datalen = hdrlen + payload_size;
878 if (frame->
m && context->is_vp9) {
879 payload_descriptor->vp9.end = 1;
887 vpx_context_t *context = (vpx_context_t *)codec->
private_info;
889 if (context->encoder_init) {
890 vpx_codec_destroy(&context->encoder);
892 context->last_ts = 0;
893 context->last_ms = 0;
894 context->framecount = 0;
895 context->encoder_init = 0;
897 return init_encoder(codec);
902 vpx_context_t *context = (vpx_context_t *)codec->
private_info;
907 vpx_enc_frame_flags_t vpx_flags = 0;
912 return consume_partition(context, frame);
915 if (context->need_encoder_reset != 0) {
919 context->need_encoder_reset = 0;
922 if (frame->
img->
d_h > 1) {
926 width = frame->
img->
w;
927 height = frame->
img->
h;
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);
935 context->need_key_frame = 3;
938 if (!context->encoder_init) {
944 if (context->change_bandwidth) {
945 context->codec_settings.video.bandwidth = context->change_bandwidth;
946 context->change_bandwidth = 0;
954 if (context->need_key_frame > 0) {
956 if (!context->last_key_frame || (now - context->last_key_frame) > vpx_globals.key_frame_min_freq) {
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;
965 context->framecount++;
967 pts = (now - context->start_time) / 1000;
970 dur = context->last_ms ? (now - context->last_ms) / 1000 : pts;
972 if ((err = vpx_codec_encode(&context->encoder,
977 VPX_DL_REALTIME)) != VPX_CODEC_OK) {
979 err, vpx_codec_error(&context->encoder), vpx_codec_error_detail(&context->encoder));
984 context->enc_iter = NULL;
986 context->last_ms = now;
988 return consume_partition(context, frame);
993 uint8_t *data = frame->
data;
999 if (context->debug > 0) {
1001 "VIDEO VPX: seq: %d ts: %u len: %u %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x mark: %d\n",
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);
1023 uint8_t M = (*data) & 0x80;
1042 if (context->got_key_frame > 0) {
1043 context->got_key_frame = 0;
1044 context->got_start_frame = 0;
1052 context->last_received_timestamp = frame->
timestamp;
1055 key = __IS_VP8_KEY_FRAME(*data);
1060 len = frame->
datalen - (data - (uint8_t *)frame->
data);
1068 if (context->last_received_timestamp != frame->
timestamp) {
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;
1087 if (context->debug > 0) {
1089 "[%02x %02x %02x %02x] m=%d len=%4d seq=%d ts=%u ssrc=%u " 1092 "have_layer_ind=%d " 1101 desc->have_layer_ind,
1111 if (desc->have_pid) {
1119 pid = (pid << 8) + *vp9;
1131 if (desc->have_layer_ind) {
1133 vp9_p_layer_t *layer = (vp9_p_layer_t *)vp9;
1136 layer->temporal_id, layer->temporal_up_switch, layer->spatial_id, layer->inter_layer_predicted);
1140 if (!desc->is_flexible) {
1146 if (desc->have_p_layer && desc->is_flexible) {
1161 if (desc->have_ss) {
1162 vp9_ss_t *ss = (vp9_ss_t *)(vp9++);
1170 for (i=0; i<=ss->n_s; i++) {
1172 int width = ntohs(*(uint16_t *)vp9);
1173 int height = ntohs(*(uint16_t *)(vp9 + 2));
1182 uint8_t ng = *vp9++;
1184 for (i = 0; ng > 0 && i < ng; i++) {
1185 vp9_n_g_t *n_g = (vp9_n_g_t *)(vp9++);
1191 if (vp9 - data >= frame->
datalen) {
1204 len = frame->
datalen - (vp9 - data);
1218 vpx_context_t *context = (vpx_context_t *)codec->
private_info;
1220 vpx_codec_ctx_t *decoder = NULL;
1222 int is_start = 0, is_keyframe = 0, get_refresh = 0;
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;
1228 *data, *(data+1), *(data+2), *(data+3), frame->
m, desc->start, desc->end, frame->
m, frame->
datalen);
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);
1239 if (context->last_received_seq && context->last_received_seq + 1 != frame->
seq) {
1244 context->last_received_seq = frame->
seq;
1246 is_start = (*(
unsigned char *)frame->
data & 0x10);
1247 is_keyframe = IS_VP8_KEY_FRAME((uint8_t *)frame->
data);
1250 if (!is_keyframe && context->got_key_frame <= 0) {
1251 context->no_key_frame++;
1253 if (context->no_key_frame > 50) {
1254 if ((is_keyframe = is_start)) {
1260 if (context->debug > 0 && is_keyframe) {
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;
1273 if (!context->decoder_init) {
1274 status = init_decoder(codec);
1279 if (!context->decoder_init) {
1284 decoder = &context->decoder;
1292 context->got_start_frame = 1;
1297 if (context->got_key_frame <= 0) {
1298 context->got_key_frame = 1;
1299 context->no_key_frame = 0;
1301 context->got_key_frame++;
1303 }
else if (context->got_key_frame <= 0) {
1304 if ((--context->got_key_frame % 200) == 0) {
1310 if (!context->got_start_frame) {
1316 status = context->is_vp9 ? buffer_vp9_packets(context, frame) : buffer_vp8_packets(context, frame);
1319 if (context->dec_iter && (frame->
img = (
switch_image_t *) vpx_codec_get_frame(decoder, &context->dec_iter))) {
1334 vpx_codec_err_t err;
1338 context->dec_iter = NULL;
1339 err = vpx_codec_decode(decoder, data, (
unsigned int)len, NULL, 0);
1341 if (err != VPX_CODEC_OK) {
1344 len, err, vpx_codec_error(decoder), vpx_codec_error_detail(decoder));
1346 if (err == VPX_CODEC_MEM_ERROR) {
1348 context->need_decoder_reset = 1;
1353 if (!context->decoded_first_frame) context->decoded_first_frame = 1;
1356 if (vpx_codec_control(decoder, VP8D_GET_FRAME_CORRUPTED, &corrupted) != VPX_CODEC_OK) {
1367 frame->
img = (
switch_image_t *) vpx_codec_get_frame(decoder, &context->dec_iter);
1378 context->got_key_frame = 0;
1379 context->got_start_frame = 0;
1389 context->got_key_frame = 0;
1390 context->got_start_frame = 0;
1398 if (context->got_key_frame <= 0 || get_refresh) {
1405 frame->
img = context->patch_img;
1422 vpx_context_t *context = (vpx_context_t *)codec->
private_info;
1427 int mask = *((
int *) cmd_data);
1429 context->need_encoder_reset = 1;
1432 context->need_decoder_reset = 1;
1437 context->need_key_frame = 1;
1443 context->change_bandwidth = *((
int *) cmd_data);
1447 char *bwv = (
char *) cmd_data;
1458 const char *command = (
const char *)cmd_data;
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);
1475 int32_t level = *((uint32_t *) cmd_data);
1476 context->debug = level;
1490 vpx_context_t *context = (vpx_context_t *)codec->
private_info;
1497 vpx_codec_destroy(&context->encoder);
1501 vpx_codec_destroy(&context->decoder);
1506 context->pic = NULL;
1508 if (context->vpx_packet_buffer) {
1510 context->vpx_packet_buffer = NULL;
1516 static void init_vp8(my_vpx_cfg_t *my_cfg)
1518 vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &my_cfg->enc_cfg, 0);
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;
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;
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;
1542 static void init_vp9(my_vpx_cfg_t *my_cfg)
1544 vpx_codec_enc_config_default(vpx_codec_vp9_cx(), &my_cfg->enc_cfg, 0);
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;
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;
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;
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));
1576 memset(vpx_globals.profiles[i], 0,
sizeof(my_vpx_cfg_t));
1579 if (!strcmp(name,
"vp9")) {
1580 init_vp9(vpx_globals.profiles[i]);
1582 init_vp8(vpx_globals.profiles[i]);
1587 return vpx_globals.profiles[i];
1590 if (!strcmp(name, vpx_globals.profiles[i]->name)) {
1592 memset(vpx_globals.profiles[i], 0,
sizeof(my_vpx_cfg_t));
1596 return vpx_globals.profiles[i];
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) 1612 static void parse_profile(my_vpx_cfg_t *my_cfg,
switch_xml_t profile,
int codec_type)
1615 const char *profile_name = profile->
name;
1617 vpx_codec_dec_cfg_t *dec_cfg = NULL;
1618 vpx_codec_enc_cfg_t *enc_cfg = NULL;
1620 dec_cfg = &my_cfg->dec_cfg;
1621 enc_cfg = &my_cfg->enc_cfg;
1628 if (!enc_cfg || !dec_cfg)
break;
1629 if (
zstr(name) ||
zstr(value))
continue;
1635 if (!strcmp(name,
"dec-threads")) {
1637 }
else if (!strcmp(name,
"enc-threads")) {
1639 }
else if (!strcmp(name,
"g-profile")) {
1640 _VPX_CHECK_MIN_MAX(enc_cfg->g_profile, val, 0, 3);
1642 }
else if (!strcmp(name,
"g-timebase")) {
1645 char *slash = strchr(value,
'/');
1653 if (den < 0) den = 0;
1657 enc_cfg->g_timebase.num = num;
1658 enc_cfg->g_timebase.den = den;
1661 }
else if (!strcmp(name,
"g-error-resilient")) {
1662 char *s = strdup(value);
1664 vpx_codec_er_flags_t res = 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;
1676 _VPX_CHECK_ERR(
"has invalid token \"%s\"", argv[i]);
1681 enc_cfg->g_error_resilient = res;
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;
1691 _VPX_CHECK_ERRDEF_INVL(enc_cfg->g_pass);
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;
1717 _VPX_CHECK_ERRDEF_INVL(enc_cfg->rc_end_usage);
1719 }
else if (!strcmp(name,
"rc-target-bitrate")) {
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);
1729 _VPX_CHECK_MIN_MAX(enc_cfg->rc_undershoot_pct, val, 0, 1000);
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);
1735 _VPX_CHECK_MIN_MAX(enc_cfg->rc_overshoot_pct, val, 0, 1000);
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;
1755 _VPX_CHECK_ERRDEF_INVL(enc_cfg->kf_mode);
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);
1769 _VPX_CHECK_ERRDEF_NOTAPPL(enc_cfg->ts_number_layers);
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);
1775 _VPX_CHECK_MIN_MAX(enc_cfg->ts_periodicity, val, 0, 16);
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);
1781 _VPX_CHECK_MIN_MAX(enc_cfg->temporal_layering_mode, val, 0, 3);
1783 }
else if (!strcmp(name,
"lossless")) {
1784 if (codec_type == CODEC_TYPE_VP9) {
1785 _VPX_CHECK_MIN_MAX(my_cfg->lossless, val, 0, 1);
1787 _VPX_CHECK_ERRDEF_NOTAPPL(my_cfg->lossless);
1789 }
else if (!strcmp(name,
"cpuused")) {
1790 if (codec_type == CODEC_TYPE_VP8) {
1791 _VPX_CHECK_MIN_MAX(my_cfg->cpuused, val, -16, 16);
1793 _VPX_CHECK_MIN_MAX(my_cfg->cpuused, val, -8, 8);
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);
1803 _VPX_CHECK_ERRDEF_NOTAPPL(my_cfg->noise_sensitivity);
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);
1809 _VPX_CHECK_ERRDEF_NOTAPPL(my_cfg->max_intra_bitrate_pct);
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;
1818 _VPX_CHECK_ERRDEF_INVL(my_cfg->tune_content);
1821 _VPX_CHECK_ERRDEF_NOTAPPL(my_cfg->tune_content);
1827 static void parse_codecs(my_vpx_cfg_t *my_cfg,
switch_xml_t codecs)
1838 if (my_cfg->codecs) {
1844 for (; codec; codec = codec->
next) {
1848 if (
zstr(name) ||
zstr(profile))
continue;
1859 my_vpx_cfg_t *my_cfg = NULL;
1861 memset(&vpx_globals, 0,
sizeof(vpx_globals));
1864 vpx_globals.rtp_slice_size = SLICE_SIZE;
1865 vpx_globals.key_frame_min_freq = KEY_FRAME_MIN_FREQ;
1877 const char *profile_name =
"settings";
1881 if (
zstr(name) ||
zstr(value))
continue;
1883 if (!strcmp(name,
"debug")) {
1884 vpx_globals.debug = atoi(value);
1885 }
else if (!strcmp(name,
"max-bitrate")) {
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")) {
1893 _VPX_CHECK_MIN(vpx_globals.dec_threads, val, 1);
1894 }
else if (!strcmp(name,
"enc-threads")) {
1896 _VPX_CHECK_MIN(vpx_globals.enc_threads, val, 1);
1904 for (; profile; profile = profile->
next) {
1907 my_vpx_cfg_t *my_cfg = NULL;
1909 if (
zstr(profile_name))
continue;
1911 my_cfg = find_cfg_profile(profile_name,
SWITCH_TRUE);
1913 if (!my_cfg)
continue;
1915 parse_profile(my_cfg, profile, CODEC_TYPE(profile_name));
1916 parse_codecs(my_cfg, codecs);
1923 if (vpx_globals.max_bitrate <= 0) {
1927 if (vpx_globals.rtp_slice_size < 500 || vpx_globals.rtp_slice_size > 1500) {
1928 vpx_globals.rtp_slice_size = SLICE_SIZE;
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;
1938 if (!my_cfg->enc_cfg.g_threads) my_cfg->enc_cfg.g_threads = 1;
1945 if (!my_cfg->enc_cfg.g_threads) my_cfg->enc_cfg.g_threads = 1;
1950 #define VPX_API_SYNTAX "<reload|debug <on|off>>" 1961 if (!strcasecmp(cmd,
"reload")) {
1963 my_vpx_cfg_t *my_cfg;
1967 stream->write_function(stream,
"Reload XML [%s]\n", err);
1974 for (i = 0; i < MAX_PROFILES; i++) {
1975 my_cfg = vpx_globals.profiles[i];
1979 if (!strcmp(my_cfg->name,
"vp8")) {
1981 }
else if (!strcmp(my_cfg->name,
"vp9")) {
1987 show_config(my_cfg, &my_cfg->enc_cfg);
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");
2004 stream->write_function(stream,
"USAGE: %s\n", VPX_API_SYNTAX);
2013 memset(&vpx_globals, 0,
sizeof(
struct vpx_globals));
2021 switch_vpx_init, switch_vpx_encode, switch_vpx_decode, switch_vpx_control, switch_vpx_destroy);
2024 switch_vpx_init, switch_vpx_encode, switch_vpx_decode, switch_vpx_control, switch_vpx_destroy);
2027 "VPX API", vpx_api_function, VPX_API_SYNTAX);
2042 for (i = 0; i < MAX_PROFILES; i++) {
2043 my_vpx_cfg_t *my_cfg = vpx_globals.profiles[i];
2047 if (my_cfg->codecs) {
switch_core_session_t * session
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
switch_status_t switch_console_set_complete(const char *string)
void switch_xml_free(_In_opt_ switch_xml_t xml)
frees the memory allocated for an switch_xml structure
#define VPX_IMAGE_ABI_VERSION
Current ABI version number.
void vpx_img_free(vpx_image_t *img)
Close an image descriptor.
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
#define SWITCH_CHANNEL_LOG
switch_size_t switch_buffer_read(_In_ switch_buffer_t *buffer, _In_ void *data, _In_ switch_size_t datalen)
Read data from a switch_buffer_t up to the ammount of datalen if it is available. Remove read data fr...
const char * switch_xml_attr(_In_opt_ switch_xml_t xml, _In_opt_z_ const char *attr)
returns the value of the requested tag attribute, or NULL if not found
void switch_img_free(switch_image_t **img)
Close an image descriptor.
static switch_status_t load_config(void)
switch_status_t switch_buffer_create_dynamic(_Out_ switch_buffer_t **buffer, _In_ switch_size_t blocksize, _In_ switch_size_t start_len, _In_ switch_size_t max_len)
Allocate a new dynamic switch_buffer.
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
switch_memory_pool_t * pool
Representation of an event.
const char *const const char *const const cJSON *const value
A representation of an XML tree.
uint32_t switch_core_cpu_count(void)
#define SWITCH_MODULE_SHUTDOWN_FUNCTION(name)
switch_status_t switch_xml_reload(const char **err)
char const int const cJSON_bool format
static int32_t switch_calc_bitrate(int w, int h, float quality, double fps)
switch_size_t switch_buffer_write(_In_ switch_buffer_t *buffer, _In_bytecount_(datalen) const void *data, _In_ switch_size_t datalen)
Write data into a switch_buffer_t up to the length of datalen.
static int32_t switch_parse_bandwidth_string(const char *bwv)
static uint32_t switch_parse_cpu_string(const char *cpu)
uint32_t switch_codec_flag_t
switch_status_t switch_buffer_create_partition(switch_memory_pool_t *pool, switch_buffer_t **buffer, void *data, switch_size_t datalen)
switch_codec_control_command_t
static const char usage[]
switch_codec_control_type_t
const switch_codec_implementation_t * implementation
if((uint32_t)(unpack->cur - unpack->buf) > unpack->buflen)
unsigned int switch_separate_string(_In_ char *buf, char delim, _Post_count_(return) char **array, unsigned int arraylen)
Separate a string into an array based on a character delimiter.
A module interface to implement an api function.
switch_frame_flag_t flags
#define SWITCH_STANDARD_API(name)
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
switch_memory_pool_t * memory_pool
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
void switch_img_copy(switch_image_t *img, switch_image_t **new_img)
Copy image to a new image.
Top level module interface to implement a series of codec implementations.
void switch_buffer_zero(_In_ switch_buffer_t *buffer)
Remove all data from the buffer.
#define SWITCH_CHANNEL_LOG_CLEAN
An abstraction of a data frame.
#define SWITCH_MODULE_LOAD_FUNCTION(name)
#define SWITCH_ADD_CODEC(codec_int, int_name)
switch_status_t
Common return values.
static void switch_core_codec_add_video_implementation(switch_memory_pool_t *pool, switch_codec_interface_t *codec_interface, switch_payload_t ianacode, const char *iananame, char *fmtp, switch_core_codec_init_func_t init, switch_core_codec_video_encode_func_t encode, switch_core_codec_video_decode_func_t decode, switch_core_codec_control_func_t control, switch_core_codec_destroy_func_t destroy)
#define switch_goto_status(_status, _label)
switch_xml_t switch_xml_open_cfg(_In_z_ const char *file_path, _Out_ switch_xml_t *node, _In_opt_ switch_event_t *params)
open a config in the core registry
switch_loadable_module_interface_t * switch_loadable_module_create_module_interface(switch_memory_pool_t *pool, const char *name)
switch_size_t switch_buffer_peek_zerocopy(_In_ switch_buffer_t *buffer, _Out_ const void **ptr)
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
#define SWITCH_MODULE_DEFINITION(name, load, shutdown, runtime)
switch_xml_t switch_xml_child(_In_ switch_xml_t xml, _In_z_ const char *name)
returns the first child tag (one level deeper) with the given name or NULL \ if not found ...
#define SWITCH_ADD_API(api_int, int_name, descript, funcptr, syntax_string)
#define switch_set_string(_dst, _src)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
struct fspr_pool_t switch_memory_pool_t
void switch_event_destroy(switch_event_t **event)
Destroy an event.
switch_status_t switch_buffer_set_partition_data(switch_buffer_t *buffer, void *data, switch_size_t datalen)
switch_time_t switch_time_now(void)
switch_size_t switch_buffer_inuse(_In_ switch_buffer_t *buffer)
Get the in use amount of a switch_buffer_t.
void switch_buffer_destroy(switch_buffer_t **buffer)
Destroy the buffer.