static switch_status_t switch_vpx_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings) { vpx_context_t *context = NULL; int encoding, decoding; encoding = (flags & SWITCH_CODEC_FLAG_ENCODE); decoding = (flags & SWITCH_CODEC_FLAG_DECODE); if (!(encoding || decoding) || ((context = switch_core_alloc(codec->memory_pool, sizeof(*context))) == 0)) { return SWITCH_STATUS_FALSE; } memset(context, 0, sizeof(*context)); context->flags = flags; codec->private_info = context; context->pool = codec->memory_pool; if (codec_settings) { context->codec_settings = *codec_settings; } if (!strcmp(codec->implementation->iananame, "VP9")) { context->is_vp9 = 1; context->encoder_interface = vpx_codec_vp9_cx(); context->decoder_interface = vpx_codec_vp9_dx(); } else { context->encoder_interface = vpx_codec_vp8_cx(); context->decoder_interface = vpx_codec_vp8_dx(); } if (codec->fmtp_in) { codec->fmtp_out = switch_core_strdup(codec->memory_pool, codec->fmtp_in); } if (vpx_codec_enc_config_default(context->encoder_interface, &context->config, 0) != VPX_CODEC_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Encoder config Error\n"); return SWITCH_STATUS_FALSE; } context->codec_settings.video.width = 320; context->codec_settings.video.height = 240; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VPX VER:%s VPX_IMAGE_ABI_VERSION:%d VPX_CODEC_ABI_VERSION:%d\n", vpx_codec_version_str(), VPX_IMAGE_ABI_VERSION, VPX_CODEC_ABI_VERSION); return SWITCH_STATUS_SUCCESS; }
krad_vpx_encoder_t *krad_vpx_encoder_create (int width, int height, int fps_numerator, int fps_denominator, int bitrate) { krad_vpx_encoder_t *kradvpx; kradvpx = calloc(1, sizeof(krad_vpx_encoder_t)); kradvpx->width = width; kradvpx->height = height; kradvpx->fps_numerator = fps_numerator; kradvpx->fps_denominator = fps_denominator; kradvpx->bitrate = bitrate; printk ("Krad Radio using libvpx version: %s", vpx_codec_version_str ()); if ((kradvpx->image = vpx_img_alloc (NULL, VPX_IMG_FMT_YV12, kradvpx->width, kradvpx->height, 1)) == NULL) { failfast ("Failed to allocate vpx image\n"); } kradvpx->res = vpx_codec_enc_config_default (vpx_codec_vp8_cx(), &kradvpx->cfg, 0); if (kradvpx->res) { failfast ("Failed to get config: %s\n", vpx_codec_err_to_string(kradvpx->res)); } // print default config //krad_vpx_encoder_print_config (kradvpx); kradvpx->cfg.g_w = kradvpx->width; kradvpx->cfg.g_h = kradvpx->height; /* Next two lines are really right */ kradvpx->cfg.g_timebase.num = kradvpx->fps_denominator; kradvpx->cfg.g_timebase.den = kradvpx->fps_numerator; kradvpx->cfg.rc_target_bitrate = bitrate; kradvpx->cfg.g_threads = 4; kradvpx->cfg.kf_mode = VPX_KF_AUTO; kradvpx->cfg.rc_end_usage = VPX_VBR; kradvpx->deadline = 15 * 1000; kradvpx->min_quantizer = kradvpx->cfg.rc_min_quantizer; kradvpx->max_quantizer = kradvpx->cfg.rc_max_quantizer; //krad_vpx_encoder_print_config (kradvpx); if (vpx_codec_enc_init(&kradvpx->encoder, vpx_codec_vp8_cx(), &kradvpx->cfg, 0)) { krad_vpx_fail (&kradvpx->encoder, "Failed to initialize encoder"); } //krad_vpx_encoder_print_config (kradvpx); #ifdef BENCHMARK printk ("Benchmarking enabled, reporting every %d frames", BENCHMARK_COUNT); kradvpx->krad_timer = krad_timer_create(); #endif return kradvpx; }
krad_vpx_encoder_t *krad_vpx_encoder_create (int width, int height, int fps_numerator, int fps_denominator, int bitrate) { krad_vpx_encoder_t *vpx; vpx = calloc (1, sizeof(krad_vpx_encoder_t)); vpx->width = width; vpx->height = height; vpx->fps_numerator = fps_numerator; vpx->fps_denominator = fps_denominator; vpx->bitrate = bitrate; printk ("Krad Radio using libvpx version: %s", vpx_codec_version_str ()); vpx->res = vpx_codec_enc_config_default (vpx_codec_vp8_cx(), &vpx->cfg, 0); if (vpx->res) { failfast ("Failed to get config: %s\n", vpx_codec_err_to_string(vpx->res)); } printk ("For reference the default config is:"); krad_vpx_encoder_print_config (vpx); vpx->cfg.g_w = vpx->width; vpx->cfg.g_h = vpx->height; /* Next two lines are really right */ vpx->cfg.g_timebase.num = vpx->fps_denominator; vpx->cfg.g_timebase.den = vpx->fps_numerator; vpx->cfg.rc_target_bitrate = bitrate; vpx->cfg.g_threads = 4; vpx->cfg.kf_mode = VPX_KF_AUTO; vpx->cfg.rc_end_usage = VPX_VBR; vpx->cfg.kf_max_dist = 120; vpx->deadline = 15 * 1000; vpx->min_quantizer = vpx->cfg.rc_min_quantizer; vpx->max_quantizer = vpx->cfg.rc_max_quantizer; if (vpx_codec_enc_init (&vpx->encoder, vpx_codec_vp8_cx(), &vpx->cfg, 0)) { krad_vpx_fail (&vpx->encoder, "Failed to initialize encoder"); } krad_vpx_encoder_print_config (vpx); return vpx; }
int Ebml_WriteWebMSeekInfo(EbmlGlobal *ebml) { int rc = VINF_SUCCESS; /* Save the current file pointer */ uint64_t pos = RTFileTell(ebml->file); if (ebml->seek_info_pos) rc = RTFileSeek(ebml->file, ebml->seek_info_pos, RTFILE_SEEK_BEGIN, NULL); else ebml->seek_info_pos = pos; { uint64_t start; if (RT_SUCCESS(rc)) rc = ebml_StartSubElement(ebml, &start, SeekHead); if (RT_SUCCESS(rc)) rc = Ebml_WriteWebMSeekElement(ebml, Tracks, ebml->track_pos); if (RT_SUCCESS(rc)) rc = Ebml_WriteWebMSeekElement(ebml, Cues, ebml->cue_pos); if (RT_SUCCESS(rc)) rc = Ebml_WriteWebMSeekElement(ebml, Info, ebml->segment_info_pos); if (RT_SUCCESS(rc)) rc = ebml_EndSubElement(ebml, start); } { //segment info uint64_t startInfo; uint64_t frame_time; frame_time = (uint64_t)1000 * ebml->framerate.den / ebml->framerate.num; ebml->segment_info_pos = RTFileTell(ebml->file); if (RT_SUCCESS(rc)) rc = ebml_StartSubElement(ebml, &startInfo, Info); if (RT_SUCCESS(rc)) rc = Ebml_SerializeUnsigned(ebml, TimecodeScale, 1000000); if (RT_SUCCESS(rc)) rc = Ebml_SerializeFloat(ebml, Segment_Duration, (double)(ebml->last_pts_ms + frame_time)); char szVersion[64]; RTStrPrintf(szVersion, sizeof(szVersion), "vpxenc%", ebml->debug ? vpx_codec_version_str() : ""); if (RT_SUCCESS(rc)) rc = Ebml_SerializeString(ebml, MuxingApp, szVersion); if (RT_SUCCESS(rc)) rc = Ebml_SerializeString(ebml, WritingApp, szVersion); if (RT_SUCCESS(rc)) rc = ebml_EndSubElement(ebml, startInfo); } return rc; }
void write_webm_seek_info(struct EbmlGlobal *ebml) { off_t pos; EbmlLoc start; EbmlLoc startInfo; uint64_t frame_time; char version_string[64]; /* Save the current stream pointer. */ pos = ftello(ebml->stream); if (ebml->seek_info_pos) fseeko(ebml->stream, ebml->seek_info_pos, SEEK_SET); else ebml->seek_info_pos = pos; Ebml_StartSubElement(ebml, &start, SeekHead); write_webm_seek_element(ebml, Tracks, ebml->track_pos); write_webm_seek_element(ebml, Cues, ebml->cue_pos); write_webm_seek_element(ebml, Info, ebml->segment_info_pos); Ebml_EndSubElement(ebml, &start); /* Create and write the Segment Info. */ if (ebml->debug) { strcpy(version_string, "vpxenc"); } else { strcpy(version_string, "vpxenc "); strncat(version_string, vpx_codec_version_str(), sizeof(version_string) - 1 - strlen(version_string)); } frame_time = (uint64_t)1000 * ebml->framerate.den / ebml->framerate.num; ebml->segment_info_pos = ftello(ebml->stream); Ebml_StartSubElement(ebml, &startInfo, Info); Ebml_SerializeUnsigned(ebml, TimecodeScale, 1000000); Ebml_SerializeFloat(ebml, Segment_Duration, (double)(ebml->last_pts_ms + frame_time)); Ebml_SerializeString(ebml, 0x4D80, version_string); Ebml_SerializeString(ebml, 0x5741, version_string); Ebml_EndSubElement(ebml, &startInfo); }
//------------------------------------------------------------------ void write_webm_seek_info(EbmlGlobal *global) { off_t pos; off_t start; off_t startInfo; uint64_t frame_time; char version_string[64]; /* Save the current stream pointer. */ pos = ftello(global->stream); if (global->seek_info_pos) { fseeko(global->stream, global->seek_info_pos, SEEK_SET); } else { global->seek_info_pos = pos; } Ebml_StartSubElement(global, &start, SeekHead); write_webm_seek_element(global, Tracks, global->track_pos); write_webm_seek_element(global, Cues, global->cue_pos); write_webm_seek_element(global, Info, global->segment_info_pos); Ebml_EndSubElement(global, &start); /* Create and write the Segment Info. */ strcpy(version_string, "DesktopCapture v1.0 - libVPX "); strncat(version_string, vpx_codec_version_str(), sizeof(version_string) - 1 - strlen(version_string)); frame_time = (uint64_t) 1000 * global->framerate.den / global->framerate.num; global->segment_info_pos = ftello(global->stream); Ebml_StartSubElement(global, &startInfo, Info); Ebml_SerializeUnsigned(global, TimecodeScale, 1000000); Ebml_SerializeFloat(global, Segment_Duration, (double) (global->last_pts_ms + frame_time)); Ebml_SerializeString(global, MuxingApp, version_string); Ebml_SerializeString(global, WritingApp, version_string); Ebml_EndSubElement(global, &startInfo); }
/***************************************************************************** * Open: probe the decoder *****************************************************************************/ static int Open(vlc_object_t *p_this) { decoder_t *dec = (decoder_t *)p_this; const struct vpx_codec_iface *iface; int vp_version; switch (dec->fmt_in.i_codec) { #ifdef ENABLE_VP8_DECODER case VLC_CODEC_VP8: iface = &vpx_codec_vp8_dx_algo; vp_version = 8; break; #endif #ifdef ENABLE_VP9_DECODER case VLC_CODEC_VP9: iface = &vpx_codec_vp9_dx_algo; vp_version = 9; break; #endif default: return VLC_EGENERIC; } decoder_sys_t *sys = malloc(sizeof(*sys)); if (!sys) return VLC_ENOMEM; dec->p_sys = sys; struct vpx_codec_dec_cfg deccfg = { .threads = __MIN(vlc_GetCPUCount(), 16) }; msg_Dbg(p_this, "VP%d: using libvpx version %s (build options %s)", vp_version, vpx_codec_version_str(), vpx_codec_build_config()); if (vpx_codec_dec_init(&sys->ctx, iface, &deccfg, 0) != VPX_CODEC_OK) { const char *error = vpx_codec_error(&sys->ctx); msg_Err(p_this, "Failed to initialize decoder: %s\n", error); free(sys); return VLC_EGENERIC;; } dec->pf_decode_video = Decode; dec->fmt_out.i_cat = VIDEO_ES; dec->fmt_out.video.i_width = dec->fmt_in.video.i_width; dec->fmt_out.video.i_height = dec->fmt_in.video.i_height; dec->fmt_out.i_codec = VLC_CODEC_I420; dec->b_need_packetized = true; return VLC_SUCCESS; } /***************************************************************************** * Close: decoder destruction *****************************************************************************/ static void Close(vlc_object_t *p_this) { decoder_t *dec = (decoder_t *)p_this; decoder_sys_t *sys = dec->p_sys; /* Free our PTS */ const void *iter = NULL; for (;;) { struct vpx_image *img = vpx_codec_get_frame(&sys->ctx, &iter); if (!img) break; free(img->user_priv); } vpx_codec_destroy(&sys->ctx); free(sys); }
/* * Open codec. */ static pj_status_t pj_vpx_codec_open(pjmedia_vid_codec *codec, pjmedia_vid_codec_param *attr) { vpx_private *vpx; pj_status_t status; PJ_ASSERT_RETURN(codec && attr, PJ_EINVAL); vpx = (vpx_private*) codec->codec_data; pj_memcpy(&vpx->param, attr, sizeof(*attr)); /* Normalize encoding MTU in codec param */ if (attr->enc_mtu > PJMEDIA_MAX_VID_PAYLOAD_SIZE) { attr->enc_mtu = PJMEDIA_MAX_VID_PAYLOAD_SIZE; } /* Init format info and apply-param of decoder */ vpx->dec_vfi = pjmedia_get_video_format_info(NULL, vpx->param.dec_fmt.id); if (!vpx->dec_vfi) { status = PJ_EINVAL; goto on_error; } pj_bzero(&vpx->dec_vafp, sizeof(vpx->dec_vafp)); vpx->dec_vafp.size = vpx->param.dec_fmt.det.vid.size; vpx->dec_vafp.buffer = NULL; status = (*vpx->dec_vfi->apply_fmt)(vpx->dec_vfi, &vpx->dec_vafp); if (status != PJ_SUCCESS) { goto on_error; } /* Init format info and apply-param of encoder */ vpx->enc_vfi = pjmedia_get_video_format_info(NULL, vpx->param.dec_fmt.id); if (!vpx->enc_vfi) { status = PJ_EINVAL; goto on_error; } pj_bzero(&vpx->enc_vafp, sizeof(vpx->enc_vafp)); vpx->enc_vafp.size = vpx->param.enc_fmt.det.vid.size; vpx->enc_vafp.buffer = NULL; status = (*vpx->enc_vfi->apply_fmt)(vpx->enc_vfi, &vpx->enc_vafp); if (status != PJ_SUCCESS) { goto on_error; } /* Open the encoder */ TRACE_((THIS_FILE, "Open vpx version : %s build : %s", vpx_codec_version_str(), vpx_codec_build_config())); if (vpx->param.dir & PJMEDIA_DIR_ENCODING) { status = pj_vpx_encoder_open(vpx); if (status != PJ_SUCCESS) { goto on_error; } } if (vpx->param.dir & PJMEDIA_DIR_DECODING) { status = pj_vpx_decoder_open(vpx); if (status != PJ_SUCCESS) { goto on_error; } } /* Update codec attributes, e.g: encoding format may be changed by * SDP fmtp negotiation. */ pj_memcpy(attr, &vpx->param, sizeof(*attr)); return PJ_SUCCESS; on_error: pj_vpx_codec_close(codec); return status; }