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 krad_vpx_encoder_write (krad_vpx_encoder_t *vpx, unsigned char **packet, int *keyframe) { if (vpx->update_config == 1) { krad_vpx_encoder_config_set (vpx, &vpx->cfg); vpx->update_config = 0; krad_vpx_encoder_print_config (vpx); } if (vpx_codec_encode (&vpx->encoder, vpx->image, vpx->frames, 1, vpx->flags, vpx->deadline)) { krad_vpx_fail (&vpx->encoder, "Failed to encode frame"); } vpx->frames++; vpx->flags = 0; vpx->iter = NULL; while ((vpx->pkt = vpx_codec_get_cx_data (&vpx->encoder, &vpx->iter))) { //printkd ("Got packet\n"); if (vpx->pkt->kind == VPX_CODEC_CX_FRAME_PKT) { *packet = vpx->pkt->data.frame.buf; *keyframe = vpx->pkt->data.frame.flags & VPX_FRAME_IS_KEY; if (*keyframe == 0) { vpx->frames_since_keyframe++; } else { vpx->frames_since_keyframe = 0; //printkd ("keyframe is %d pts is -%ld-\n", // *keyframe, vpx->pkt->data.frame.pts); } vpx->bytes += vpx->pkt->data.frame.sz; return vpx->pkt->data.frame.sz; } } return 0; }
int32_t kr_vpx_encode (krad_vpx_encoder_t *vpx, kr_codeme_t *codeme, kr_medium_t *medium) { int ret; vpx_image_t image; memset (&image, 0, sizeof(vpx_image_t)); vpx_codec_iter_t iter; //vpx_codec_err_t err; //vpx_codec_cx_pkt_t *pkt; ret = 0; if (vpx->update_config == 1) { krad_vpx_encoder_config_set (vpx, &vpx->cfg); vpx->update_config = 0; krad_vpx_encoder_print_config (vpx); } if (medium == NULL) { ret = vpx_codec_encode (&vpx->encoder, NULL, vpx->frames, 1, vpx->flags, vpx->deadline); } else { vpx_img_wrap (&image, VPX_IMG_FMT_I420, vpx->width, vpx->height, 1, medium->data); //image.w = vpx->width; //image.h = vpx->height; //image.d_w = vpx->width; //image.d_h = vpx->height; //image.planes[0] = medium->v.ppx[0]; //image.planes[1] = medium->v.ppx[1]; //image.planes[2] = medium->v.ppx[2]; image.stride[0] = medium->v.pps[0]; image.stride[1] = medium->v.pps[1]; image.stride[2] = medium->v.pps[2]; ret = vpx_codec_encode (&vpx->encoder, &image, vpx->frames, 1, vpx->flags, vpx->deadline); } if (ret != 0) { printke ("oh shit"); } vpx->frames++; vpx->flags = 0; iter = NULL; vpx->pkt = vpx_codec_get_cx_data (&vpx->encoder, &iter); if (vpx->pkt != NULL) { if (vpx->pkt->kind == VPX_CODEC_CX_FRAME_PKT) { codeme->sz = vpx->pkt->data.frame.sz; memcpy (codeme->data, vpx->pkt->data.frame.buf, codeme->sz); codeme->key = vpx->pkt->data.frame.flags & VPX_FRAME_IS_KEY; if (codeme->key == 0) { vpx->frames_since_keyframe++; } else { vpx->frames_since_keyframe = 0; } return 1; } } return ret; }