int vc_reconfigure_encoder(VCSession *vc, uint32_t bit_rate, uint16_t width, uint16_t height, int16_t kf_max_dist) { if (!vc) { return -1; } vpx_codec_enc_cfg_t cfg2 = *vc->encoder->config.enc; vpx_codec_err_t rc; if (cfg2.rc_target_bitrate == bit_rate && cfg2.g_w == width && cfg2.g_h == height && kf_max_dist == -1) { return 0; /* Nothing changed */ } if (cfg2.g_w == width && cfg2.g_h == height && kf_max_dist == -1) { /* Only bit rate changed */ LOGGER_INFO(vc->log, "bitrate change from: %u to: %u", (uint32_t)cfg2.rc_target_bitrate, (uint32_t)bit_rate); cfg2.rc_target_bitrate = bit_rate; rc = vpx_codec_enc_config_set(vc->encoder, &cfg2); if (rc != VPX_CODEC_OK) { LOGGER_ERROR(vc->log, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); return -1; } } else { /* Resolution is changed, must reinitialize encoder since libvpx v1.4 doesn't support * reconfiguring encoder to use resolutions greater than initially set. */ LOGGER_DEBUG(vc->log, "Have to reinitialize vpx encoder on session %p", (void *)vc); vpx_codec_ctx_t new_c; vpx_codec_enc_cfg_t cfg; vc_init_encoder_cfg(vc->log, &cfg, kf_max_dist); cfg.rc_target_bitrate = bit_rate; cfg.g_w = width; cfg.g_h = height; LOGGER_DEBUG(vc->log, "Using VP8 codec for encoder"); rc = vpx_codec_enc_init(&new_c, video_codec_encoder_interface(), &cfg, VPX_CODEC_USE_FRAME_THREADING); if (rc != VPX_CODEC_OK) { LOGGER_ERROR(vc->log, "Failed to initialize encoder: %s", vpx_codec_err_to_string(rc)); return -1; } int cpu_used_value = VP8E_SET_CPUUSED_VALUE; rc = vpx_codec_control(&new_c, VP8E_SET_CPUUSED, cpu_used_value); if (rc != VPX_CODEC_OK) { LOGGER_ERROR(vc->log, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); vpx_codec_destroy(&new_c); return -1; } vpx_codec_destroy(vc->encoder); memcpy(vc->encoder, &new_c, sizeof(new_c)); } return 0; }
RefPtr<MediaDataDecoder::DecodePromise> VPXDecoder::ProcessDecode(MediaRawData* aSample) { MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); if (vpx_codec_err_t r = vpx_codec_decode(&mVPX, aSample->Data(), aSample->Size(), nullptr, 0)) { LOG("VPX Decode error: %s", vpx_codec_err_to_string(r)); return DecodePromise::CreateAndReject( MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR, RESULT_DETAIL("VPX error: %s", vpx_codec_err_to_string(r))), __func__); } vpx_codec_iter_t iter = nullptr; vpx_image_t *img; vpx_image_t *img_alpha = nullptr; bool alpha_decoded = false; DecodedData results; while ((img = vpx_codec_get_frame(&mVPX, &iter))) { NS_ASSERTION(img->fmt == VPX_IMG_FMT_I420 || img->fmt == VPX_IMG_FMT_I444, "WebM image format not I420 or I444"); NS_ASSERTION(!alpha_decoded, "Multiple frames per packet that contains alpha"); if (aSample->AlphaSize() > 0) { if (!alpha_decoded){ MediaResult rv = DecodeAlpha(&img_alpha, aSample); if (NS_FAILED(rv)) { return DecodePromise::CreateAndReject(rv, __func__); } alpha_decoded = true; } } // Chroma shifts are rounded down as per the decoding examples in the SDK VideoData::YCbCrBuffer b; b.mPlanes[0].mData = img->planes[0]; b.mPlanes[0].mStride = img->stride[0]; b.mPlanes[0].mHeight = img->d_h; b.mPlanes[0].mWidth = img->d_w; b.mPlanes[0].mOffset = b.mPlanes[0].mSkip = 0; b.mPlanes[1].mData = img->planes[1]; b.mPlanes[1].mStride = img->stride[1]; b.mPlanes[1].mOffset = b.mPlanes[1].mSkip = 0; b.mPlanes[2].mData = img->planes[2]; b.mPlanes[2].mStride = img->stride[2]; b.mPlanes[2].mOffset = b.mPlanes[2].mSkip = 0; if (img->fmt == VPX_IMG_FMT_I420) { b.mPlanes[1].mHeight = (img->d_h + 1) >> img->y_chroma_shift; b.mPlanes[1].mWidth = (img->d_w + 1) >> img->x_chroma_shift; b.mPlanes[2].mHeight = (img->d_h + 1) >> img->y_chroma_shift; b.mPlanes[2].mWidth = (img->d_w + 1) >> img->x_chroma_shift; } else if (img->fmt == VPX_IMG_FMT_I444) {
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; }
/** * @brief Encode video frame * * @param av Handler * @param dest Where to * @param dest_max Max size * @param input What to encode * @return int * @retval ToxAvError On error. * @retval >0 On success */ inline__ int toxav_prepare_video_frame(ToxAv *av, int32_t call_index, uint8_t *dest, int dest_max, vpx_image_t *input) { CallSpecific *call = &av->calls[call_index]; int rc = vpx_codec_encode(&call->cs->v_encoder, input, call->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US); if ( rc != VPX_CODEC_OK) { fprintf(stderr, "Could not encode video frame: %s\n", vpx_codec_err_to_string(rc)); return ErrorInternal; } ++call->cs->frame_counter; vpx_codec_iter_t iter = NULL; const vpx_codec_cx_pkt_t *pkt; int copied = 0; while ( (pkt = vpx_codec_get_cx_data(&call->cs->v_encoder, &iter)) ) { if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { if ( copied + pkt->data.frame.sz > dest_max ) return ErrorPacketTooLarge; mempcpy(dest + copied, pkt->data.frame.buf, pkt->data.frame.sz); copied += pkt->data.frame.sz; } } return copied; }
/** * @brief Receive decoded video packet. * * @param av Handler. * @param output Storage. * @return int * @retval 0 Success. * @retval ToxAvError On Error. */ inline__ int toxav_recv_video ( ToxAv *av, vpx_image_t **output) { if ( !output ) return ErrorInternal; uint8_t packet [RTP_PAYLOAD_SIZE]; int recved_size = 0; int error; do { recved_size = toxav_recv_rtp_payload(av, TypeVideo, packet); if (recved_size > 0 && ( error = vpx_codec_decode(&av->cs->v_decoder, packet, recved_size, NULL, 0) ) != VPX_CODEC_OK) fprintf(stderr, "Error decoding: %s\n", vpx_codec_err_to_string(error)); } while (recved_size > 0); vpx_codec_iter_t iter = NULL; vpx_image_t *img; img = vpx_codec_get_frame(&av->cs->v_decoder, &iter); *output = img; return 0; /* Yeah, i set output to be NULL if nothing received */ }
/** * @brief Receive decoded video packet. * * @param av Handler. * @param output Storage. * @return int * @retval 0 Success. * @retval ToxAvError On Error. */ inline__ int toxav_recv_video ( ToxAv *av, int32_t call_index, vpx_image_t **output) { if ( !output ) return ErrorInternal; if (cii(call_index, av->msi_session)) return ErrorNoCall; uint8_t packet [RTP_PAYLOAD_SIZE]; int recved_size = 0; int rc; CallSpecific *call = &av->calls[call_index]; do { recved_size = toxav_recv_rtp_payload(av, call_index, TypeVideo, packet); if (recved_size > 0 && ( rc = vpx_codec_decode(&call->cs->v_decoder, packet, recved_size, NULL, 0) ) != VPX_CODEC_OK) { LOGGER_ERROR("Error decoding video: %s\n", vpx_codec_err_to_string(rc)); return ErrorInternal; } } while (recved_size > 0); vpx_codec_iter_t iter = NULL; vpx_image_t *img; img = vpx_codec_get_frame(&call->cs->v_decoder, &iter); *output = img; return 0; }
int cs_set_video_encoder_resolution(CSSession *cs, uint16_t width, uint16_t height) { vpx_codec_enc_cfg_t cfg = *cs->v_encoder.config.enc; if (cfg.g_w == width && cfg.g_h == height) return 0; if (width * height > cs->max_width * cs->max_height) { vpx_codec_ctx_t v_encoder = cs->v_encoder; if (init_video_encoder(cs, width, height, cs->video_bitrate) == -1) { cs->v_encoder = v_encoder; return cs_ErrorSettingVideoResolution; } vpx_codec_destroy(&v_encoder); return 0; } LOGGER_DEBUG("New video resolution: %u %u", width, height); cfg.g_w = width; cfg.g_h = height; int rc = vpx_codec_enc_config_set(&cs->v_encoder, &cfg); if ( rc != VPX_CODEC_OK) { LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); return cs_ErrorSettingVideoResolution; } return 0; }
/** * @brief Encode video frame * * @param av Handler * @param dest Where to * @param dest_max Max size * @param input What to encode * @return int * @retval ToxAvError On error. * @retval >0 On success */ inline__ int toxav_prepare_video_frame(ToxAv *av, int32_t call_index, uint8_t *dest, int dest_max, vpx_image_t *input) { if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) { LOGGER_WARNING("Action on inactive call: %d", call_index); return ErrorNoCall; } CallSpecific *call = &av->calls[call_index]; reconfigure_video_encoder_resolution(call->cs, input->d_w, input->d_h); int rc = vpx_codec_encode(&call->cs->v_encoder, input, call->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US); if ( rc != VPX_CODEC_OK) { LOGGER_ERROR("Could not encode video frame: %s\n", vpx_codec_err_to_string(rc)); return ErrorInternal; } ++call->cs->frame_counter; vpx_codec_iter_t iter = NULL; const vpx_codec_cx_pkt_t *pkt; int copied = 0; while ( (pkt = vpx_codec_get_cx_data(&call->cs->v_encoder, &iter)) ) { if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { if ( copied + pkt->data.frame.sz > dest_max ) return ErrorPacketTooLarge; memcpy(dest + copied, pkt->data.frame.buf, pkt->data.frame.sz); copied += pkt->data.frame.sz; } } return copied; }
static void enc_process(MSFilter *f) { mblk_t *im,*om; uint64_t timems=f->ticker->time; uint32_t timestamp=timems*90; EncState *s=(EncState*)f->data; unsigned int flags = 0; vpx_codec_err_t err; YuvBuf yuv; ms_filter_lock(f); while((im=ms_queue_get(f->inputs[0]))!=NULL){ vpx_image_t img; om = NULL; flags = 0; ms_yuv_buf_init_from_mblk(&yuv, im); vpx_img_wrap(&img, VPX_IMG_FMT_I420, s->vconf.vsize.width, s->vconf.vsize.height, 1, yuv.planes[0]); if (video_starter_need_i_frame (&s->starter,f->ticker->time)){ /*sends an I frame at 2 seconds and 4 seconds after the beginning of the call*/ s->req_vfu=TRUE; } if (s->req_vfu){ flags = VPX_EFLAG_FORCE_KF; s->req_vfu=FALSE; } err = vpx_codec_encode(&s->codec, &img, s->frame_count, 1, flags, VPX_DL_REALTIME); if (err) { ms_error("vpx_codec_encode failed : %d %s (%s)\n", err, vpx_codec_err_to_string(err), vpx_codec_error_detail(&s->codec)); } else { vpx_codec_iter_t iter = NULL; const vpx_codec_cx_pkt_t *pkt; s->frame_count++; if (s->frame_count==1){ video_starter_first_frame (&s->starter,f->ticker->time); } while( (pkt = vpx_codec_get_cx_data(&s->codec, &iter)) ) { if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { if (pkt->data.frame.sz > 0) { om = allocb(pkt->data.frame.sz,0); memcpy(om->b_wptr, pkt->data.frame.buf, pkt->data.frame.sz); om->b_wptr += pkt->data.frame.sz; #ifdef FRAGMENT_ON_PARTITIONS vp8_fragment_and_send(f, s, om, timestamp, pkt, (pkt->data.frame.partition_id == s->token_partition_count)); #else vp8_fragment_and_send(f, s, om, timestamp, pkt, 1); #endif } } } } freemsg(im); } ms_filter_unlock(f); }
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; }
void krad_vpx_encoder_config_set (krad_vpx_encoder_t *vpx, vpx_codec_enc_cfg_t *cfg) { int ret; ret = vpx_codec_enc_config_set (&vpx->encoder, cfg); if (ret != VPX_CODEC_OK) { printke ("VPX Config problem: %s\n", vpx_codec_err_to_string (ret)); } }
void vc_iterate(VCSession *vc) { if (!vc) { return; } pthread_mutex_lock(vc->queue_mutex); struct RTPMessage *p; if (!rb_read(vc->vbuf_raw, (void **)&p)) { LOGGER_TRACE(vc->log, "no Video frame data available"); pthread_mutex_unlock(vc->queue_mutex); return; } pthread_mutex_unlock(vc->queue_mutex); const struct RTPHeader *const header = &p->header; uint32_t full_data_len; if (header->flags & RTP_LARGE_FRAME) { full_data_len = header->data_length_full; LOGGER_DEBUG(vc->log, "vc_iterate:001:full_data_len=%d", (int)full_data_len); } else { full_data_len = p->len; LOGGER_DEBUG(vc->log, "vc_iterate:002"); } LOGGER_DEBUG(vc->log, "vc_iterate: rb_read p->len=%d p->header.xe=%d", (int)full_data_len, p->header.xe); LOGGER_DEBUG(vc->log, "vc_iterate: rb_read rb size=%d", (int)rb_size(vc->vbuf_raw)); const vpx_codec_err_t rc = vpx_codec_decode(vc->decoder, p->data, full_data_len, nullptr, MAX_DECODE_TIME_US); free(p); if (rc != VPX_CODEC_OK) { LOGGER_ERROR(vc->log, "Error decoding video: %d %s", (int)rc, vpx_codec_err_to_string(rc)); return; } /* Play decoded images */ vpx_codec_iter_t iter = nullptr; for (vpx_image_t *dest = vpx_codec_get_frame(vc->decoder, &iter); dest != nullptr; dest = vpx_codec_get_frame(vc->decoder, &iter)) { if (vc->vcb) { vc->vcb(vc->av, vc->friend_number, dest->d_w, dest->d_h, (const uint8_t *)dest->planes[0], (const uint8_t *)dest->planes[1], (const uint8_t *)dest->planes[2], dest->stride[0], dest->stride[1], dest->stride[2], vc->vcb_user_data); } vpx_img_free(dest); // is this needed? none of the VPx examples show that } }
static int init_video_decoder(CSSession *cs) { int rc = vpx_codec_dec_init_ver(&cs->v_decoder, VIDEO_CODEC_DECODER_INTERFACE, NULL, 0, VPX_DECODER_ABI_VERSION); if ( rc != VPX_CODEC_OK) { LOGGER_ERROR("Init video_decoder failed: %s", vpx_codec_err_to_string(rc)); return -1; } return 0; }
static int init_video_encoder(CSSession *cs, uint16_t max_width, uint16_t max_height, uint32_t video_bitrate) { vpx_codec_enc_cfg_t cfg; int rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); if (rc != VPX_CODEC_OK) { LOGGER_ERROR("Failed to get config: %s", vpx_codec_err_to_string(rc)); return -1; } cfg.rc_target_bitrate = video_bitrate; cfg.g_w = max_width; cfg.g_h = max_height; cfg.g_pass = VPX_RC_ONE_PASS; cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT | VPX_ERROR_RESILIENT_PARTITIONS; cfg.g_lag_in_frames = 0; cfg.kf_min_dist = 0; cfg.kf_max_dist = 48; cfg.kf_mode = VPX_KF_AUTO; rc = vpx_codec_enc_init_ver(&cs->v_encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0, VPX_ENCODER_ABI_VERSION); if ( rc != VPX_CODEC_OK) { LOGGER_ERROR("Failed to initialize encoder: %s", vpx_codec_err_to_string(rc)); return -1; } rc = vpx_codec_control(&cs->v_encoder, VP8E_SET_CPUUSED, 8); if ( rc != VPX_CODEC_OK) { LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); return -1; } cs->max_width = max_width; cs->max_height = max_height; cs->video_bitrate = video_bitrate; return 0; }
int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t video_bitrate) { vpx_codec_enc_cfg_t cfg; int rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); if (rc) { LOGGER_ERROR("Failed to get config: %s", vpx_codec_err_to_string(rc)); return -1; } cfg.rc_target_bitrate = video_bitrate; cfg.g_w = width; cfg.g_h = height; rc = vpx_codec_enc_init_ver(&cs->v_encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0, VPX_ENCODER_ABI_VERSION); if ( rc != VPX_CODEC_OK) { LOGGER_ERROR("Failed to initialize encoder: %s", vpx_codec_err_to_string(rc)); return -1; } return 0; }
int x_vpx_encoder_init(vpx_codec_ctx_t *_p_encoder, int numcores, int width, int height) { int res; vpx_codec_enc_cfg_t cfg; res = vpx_codec_enc_config_default((vpx_codec_vp8_cx()), &cfg, 0); if (res) { printf("Failed to get config: %s\n", vpx_codec_err_to_string(res)); return -EBADF; } /* Update the default configuration with our settings */ printf("Initializing: %dx%d, BR=%d, cfg.g_timebase.den=%d\n", width, height, cfg.rc_target_bitrate, cfg.g_timebase.den); cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate / cfg.g_w / cfg.g_h * 2; cfg.g_w = width; cfg.g_h = height; cfg.g_profile = 0; //cfg.kf_mode = VPX_KF_AUTO; cfg.kf_max_dist = 30; //cfg.kf_min_dist = 0; cfg.g_threads = 4; cfg.g_pass = VPX_RC_ONE_PASS; cfg.rc_end_usage = VPX_CBR; if (cfg.rc_end_usage == VPX_CBR) { cfg.rc_buf_initial_sz = 2000; cfg.rc_buf_optimal_sz = 2000; cfg.rc_buf_sz = 3000; } // cfg.g_timebase.num = 1001; // cfg.g_timebase.den = 30000; if (vpx_codec_enc_init(_p_encoder, (vpx_codec_vp8_cx()), &cfg, 0)) { printf("Failed to init config: %s\n", vpx_codec_error(_p_encoder)); die_codec(_p_encoder, "vpx_codec_enc_init()"); return -ENOMEM; } return 0; }
int rxs_decoder_init(rxs_decoder* dec) { vpx_codec_err_t err; if (!dec) { return -1; } err = vpx_codec_dec_init(&dec->ctx, vpx_dx_interface, NULL, 0); if (err) { printf("Error: cannot initialize the decoder: %s.\n", vpx_codec_err_to_string(err)); return -2; } dec->img = NULL; return 0; }
static pj_status_t pj_vpx_codec_encode_begin(pjmedia_vid_codec *codec, const pjmedia_vid_encode_opt *opt, const pjmedia_frame *input, unsigned out_size, pjmedia_frame *output, pj_bool_t *has_more) { vpx_private *vpx = (vpx_private*) codec->codec_data; pj_status_t status; vpx_image_t *rawimg; vpx_enc_frame_flags_t flags = 0; pj_uint8_t *p; int i, res; PJ_ASSERT_RETURN(codec && input, PJ_EINVAL); p = (pj_uint8_t*) input->buf; *has_more = PJ_FALSE; rawimg = &vpx->rawimg; // TODO : make sure it's I420 ? if(input->size < vpx->enc_vafp.framebytes){ PJ_LOG(1, (THIS_FILE, "Frame provided is too small !")); return PJ_ETOOSMALL; } for (i = 0; i < vpx->enc_vfi->plane_cnt; ++i) { rawimg->planes[i] = p; rawimg->stride[i] = vpx->enc_vafp.strides[i]; p += vpx->enc_vafp.plane_bytes[i]; } if (opt && opt->force_keyframe) { flags |= VPX_EFLAG_FORCE_KF; } res = vpx_codec_encode(&vpx->encoder, rawimg, input->timestamp.u64, 1, flags, VPX_DL_REALTIME); if (res != VPX_CODEC_OK) { PJ_LOG(1, (THIS_FILE, "Failed to encode : %s %s", vpx_codec_err_to_string(res), vpx->encoder.err_detail)); return PJMEDIA_CODEC_EFAILED; } vpx->enc_iter = NULL; vpx->enc_frame_len = 0; vpx->enc_processed = 0; return pj_vpx_codec_encode_more(codec, out_size, output, has_more); }
void WebMEncoder::initializeVideoEncoder() { /* Populate encoder configuration */ vpx_codec_err_t res = vpx_codec_enc_config_default(&vpx_enc_vp8_algo, &cfg, 0); if (res) { fprintf(stderr, "Failed to get config: %s\n", vpx_codec_err_to_string(res)); exit(1); } if(boost::thread::hardware_concurrency()) { cfg.g_threads = boost::thread::hardware_concurrency() - 1; } /* Change the default timebase to a high enough value so that the encoder * will always create strictly increasing timestamps. */ cfg.g_timebase.num = 1; cfg.g_timebase.den = 30; // lag_in_frames allows for extra optimization at the expense of not writing frames in realtime cfg.g_lag_in_frames = 5; // Variable bit rate cfg.rc_end_usage = VPX_VBR; // Target data rate in Kbps (lowercase b) cfg.rc_target_bitrate = 1024; //1 Mbit/sec /* Never use the library's default resolution, require it be parsed * from the file or set on the command line. */ cfg.g_w = width; cfg.g_h = height; vpx_img_alloc(&raw, VPX_IMG_FMT_YV12, cfg.g_w, cfg.g_h, 1); cfg.g_pass = VPX_RC_ONE_PASS; /* Construct Encoder Context */ vpx_codec_enc_init(&encoder, &vpx_enc_vp8_algo, &cfg, 0); if(encoder.err) { printf("Failed to initialize encoder\n"); } }
static pj_status_t pj_vpx_decoder_open(vpx_private *vpx) { vpx_codec_flags_t flags = 0; vpx_codec_dec_cfg_t cfg; int res; cfg.threads = 1; cfg.h = 0; cfg.w = 0; res = vpx_codec_dec_init(&vpx->decoder, vpx_codec_vp8_dx(), &cfg, flags); if (res != VPX_CODEC_OK) { PJ_LOG(1, (THIS_FILE, "Failed to init vpx decoder : %s", vpx_codec_err_to_string(res))); return PJ_ENOMEM; } return PJ_SUCCESS; }
int reconfigure_video_encoder_bitrate(CodecState *cs, uint32_t video_bitrate) { vpx_codec_enc_cfg_t cfg = *cs->v_encoder.config.enc; if (cfg.rc_target_bitrate == video_bitrate) return 0; LOGGER_DEBUG("New video bitrate: %u", video_bitrate); cfg.rc_target_bitrate = video_bitrate; int rc = vpx_codec_enc_config_set(&cs->v_encoder, &cfg); if ( rc != VPX_CODEC_OK) { LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); return -1; } return 0; }
HRESULT InitVPXEncoder(vpx_codec_enc_cfg_t * vpxConfig, vpx_codec_ctx_t * vpxCodec, unsigned int width, unsigned int height) { //vpx_codec_ctx_t codec; vpx_codec_err_t res; printf("Using %s\n", vpx_codec_iface_name(vpx_codec_vp8_cx())); /* Populate encoder configuration */ res = vpx_codec_enc_config_default((vpx_codec_vp8_cx()), vpxConfig, 0); if (res) { printf("Failed to get VPX codec config: %s\n", vpx_codec_err_to_string(res)); return -1; } else { vpx_img_alloc(&_rawImage, VIDEO_INPUT_FORMAT, WIDTH, HEIGHT, 0); vpxConfig->g_w = width; vpxConfig->g_h = height; vpxConfig->rc_target_bitrate = 5000; // in kbps. vpxConfig->rc_min_quantizer = 20; // 50; vpxConfig->rc_max_quantizer = 30; // 60; vpxConfig->g_pass = VPX_RC_ONE_PASS; vpxConfig->rc_end_usage = VPX_CBR; //vpxConfig->kf_min_dist = 50; //vpxConfig->kf_max_dist = 50; //vpxConfig->kf_mode = VPX_KF_DISABLED; vpxConfig->g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT; vpxConfig->g_lag_in_frames = 0; vpxConfig->rc_resize_allowed = 0; /* Initialize codec */ if (vpx_codec_enc_init(vpxCodec, (vpx_codec_vp8_cx()), vpxConfig, 0)) { printf("Failed to initialize libvpx encoder.\n"); return -1; } else { return S_OK; } } }
/* * Method: codec_err_to_string */ JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1err_1to_1string (JNIEnv *env, jclass clazz, jint err, jbyteArray buf, jint buf_size) { const char *err_str = vpx_codec_err_to_string((vpx_codec_err_t) err); jbyte *buf_ptr = (*env)->GetByteArrayElements(env, buf, NULL); int i; for(i = 0; i < buf_size-1 && err_str[i] != '\0'; i++) buf_ptr[i] = (jbyte) err_str[i]; buf_ptr[i] = (jbyte) '\0'; (*env)->ReleaseByteArrayElements(env, buf, buf_ptr, 0); return i; }
static void enc_init(MSFilter *f) { vpx_codec_err_t res; MSVideoSize vsize; EncState *s=(EncState *)ms_new0(EncState,1); ms_message("Using %s\n",vpx_codec_iface_name(interface)); /* Populate encoder configuration */ res = vpx_codec_enc_config_default(interface, &s->cfg, 0); if(res) { ms_error("Failed to get config: %s\n", vpx_codec_err_to_string(res)); } if (ms_get_cpu_count() > 1) s->vconf_list = &multicore_vp8_conf_list[0]; else s->vconf_list = &vp8_conf_list[0]; MS_VIDEO_SIZE_ASSIGN(vsize, CIF); s->vconf = ms_video_find_best_configuration_for_size(s->vconf_list, vsize); s->frame_count = 0; s->cfg.g_w = s->vconf.vsize.width; s->cfg.g_h = s->vconf.vsize.height; /* encoder automatically places keyframes */ s->cfg.kf_mode = VPX_KF_AUTO; s->cfg.kf_max_dist = 300; s->cfg.rc_target_bitrate = ((float)s->vconf.required_bitrate)*0.92/1024.0; //0.9=take into account IP/UDP/RTP overhead, in average. s->cfg.g_pass = VPX_RC_ONE_PASS; /* -p 1 */ s->cfg.g_timebase.num = 1; s->cfg.g_timebase.den = s->vconf.fps; s->cfg.rc_end_usage = VPX_CBR; /* --end-usage=cbr */ #if TARGET_IPHONE_SIMULATOR s->cfg.g_threads = 1; /*workaround to remove crash on ipad simulator*/ #else s->cfg.g_threads = ms_get_cpu_count(); #endif ms_message("VP8 g_threads=%d", s->cfg.g_threads); s->cfg.rc_undershoot_pct = 95; /* --undershoot-pct=95 */ s->cfg.g_error_resilient = 1; s->cfg.g_lag_in_frames = 0; s->mtu=ms_get_payload_max_size()-1;/*-1 for the vp8 payload header*/ f->data = s; }
int VPXEncoder::InitEncoder(unsigned int width, unsigned int height) { _vpxCodec = new vpx_codec_ctx_t(); _rawImage = new vpx_image_t(); _width = width; _height = height; vpx_codec_enc_cfg_t vpxConfig; vpx_codec_err_t res; printf("Using %s\n", vpx_codec_iface_name(vpx_codec_vp8_cx())); /* Populate encoder configuration */ res = vpx_codec_enc_config_default((vpx_codec_vp8_cx()), &vpxConfig, 0); if (res) { printf("Failed to get VPX codec config: %s\n", vpx_codec_err_to_string(res)); return -1; } else { vpx_img_alloc(_rawImage, VPX_IMG_FMT_I420, width, height, 0); vpxConfig.g_w = width; vpxConfig.g_h = height; vpxConfig.rc_target_bitrate = 300; // 5000; // in kbps. vpxConfig.rc_min_quantizer = 20; // 50; vpxConfig.rc_max_quantizer = 30; // 60; vpxConfig.g_pass = VPX_RC_ONE_PASS; vpxConfig.rc_end_usage = VPX_CBR; vpxConfig.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT; vpxConfig.g_lag_in_frames = 0; vpxConfig.rc_resize_allowed = 0; vpxConfig.kf_max_dist = 20; /* Initialize codec */ if (vpx_codec_enc_init(_vpxCodec, (vpx_codec_vp8_cx()), &vpxConfig, 0)) { printf("Failed to initialize libvpx encoder.\n"); return -1; } } }
static void decode_video(ToxAv *av, CallSpecific *call, DECODE_PACKET *p) { int32_t call_index = call - av->calls; int rc = vpx_codec_decode(&call->cs->v_decoder, p->data, p->size, NULL, MAX_DECODE_TIME_US); if (rc != VPX_CODEC_OK) { LOGGER_ERROR("Error decoding video: %s\n", vpx_codec_err_to_string(rc)); } vpx_codec_iter_t iter = NULL; vpx_image_t *img; img = vpx_codec_get_frame(&call->cs->v_decoder, &iter); if (img && av->video_callback) { av->video_callback(av, call_index, img, av->video_callback_userdata); } else { LOGGER_WARNING("Video packet dropped due to missing callback or no image!"); } free(p); }
int reconfigure_video_encoder_resolution(CodecState *cs, uint16_t width, uint16_t height) { vpx_codec_enc_cfg_t cfg = *cs->v_encoder.config.enc; if (cfg.g_w == width && cfg.g_h == height) return 0; if (width * height > cs->max_width * cs->max_height) return -1; LOGGER_DEBUG("New video resolution: %u %u", width, height); cfg.g_w = width; cfg.g_h = height; int rc = vpx_codec_enc_config_set(&cs->v_encoder, &cfg); if ( rc != VPX_CODEC_OK) { LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); return -1; } return 0; }
/* Decode the given data. Note that on linux libvpx will crash at this moment when the first partition you pass into this function is not a key frame. */ int rxs_decoder_decode(rxs_decoder* dec, uint8_t* buffer, uint32_t nbytes) { vpx_codec_iter_t iter = NULL; vpx_codec_err_t err; if (!dec) { return -1; } if (!buffer) { return -2; } if (!nbytes) { return -3; } dec->img = NULL; err = vpx_codec_decode(&dec->ctx, buffer, nbytes, NULL, 0); if (err) { printf("Error: cannot decode buffer: %s\n", vpx_codec_err_to_string(err)); return -4; } while ( (dec->img = vpx_codec_get_frame(&dec->ctx, &iter)) ) { dec->on_image(dec, dec->img); } return 0; }
static void enc_preprocess(MSFilter *f) { vpx_codec_err_t res; EncState *s=(EncState*)f->data; s->cfg.g_w = s->vconf.vsize.width; s->cfg.g_h = s->vconf.vsize.height; s->cfg.g_timebase.den=s->vconf.fps; /* Initialize codec */ #ifdef FRAGMENT_ON_PARTITIONS /* VPX_CODEC_USE_OUTPUT_PARTITION: output 1 frame per partition */ res = vpx_codec_enc_init(&s->codec, interface, &s->cfg, VPX_CODEC_USE_OUTPUT_PARTITION); #else res = vpx_codec_enc_init(&s->codec, interface, &s->cfg, 0); #endif if (res) { ms_error("vpx_codec_enc_init failed: %s (%s)n", vpx_codec_err_to_string(res), vpx_codec_error_detail(&s->codec)); } /*cpu/quality tradeoff: positive values decrease CPU usage at the expense of quality*/ vpx_codec_control(&s->codec, VP8E_SET_CPUUSED, (s->cfg.g_threads > 1) ? 10 : 10); vpx_codec_control(&s->codec, VP8E_SET_STATIC_THRESHOLD, 0); vpx_codec_control(&s->codec, VP8E_SET_ENABLEAUTOALTREF, 1); if (s->cfg.g_threads > 1) { if (vpx_codec_control(&s->codec, VP8E_SET_TOKEN_PARTITIONS, 2) != VPX_CODEC_OK) { ms_error("VP8: failed to set multiple token partition"); } else { ms_message("VP8: multiple token partitions used"); } } #ifdef FRAGMENT_ON_PARTITIONS vpx_codec_control(&s->codec, VP8E_SET_TOKEN_PARTITIONS, 0x3); s->token_partition_count = 8; #endif /* vpx_codec_control(&s->codec, VP8E_SET_CPUUSED, 0);*/ /* -16 (quality) .. 16 (speed) */ video_starter_init(&s->starter); s->ready=TRUE; }
static void enc_init(MSFilter *f) { vpx_codec_err_t res; EncState *s=(EncState *)ms_new0(EncState,1); ms_message("Using %s\n",vpx_codec_iface_name(interface)); /* Populate encoder configuration */ res = vpx_codec_enc_config_default(interface, &s->cfg, 0); if(res) { ms_error("Failed to get config: %s\n", vpx_codec_err_to_string(res)); } s->width = MS_VIDEO_SIZE_CIF_W; s->height = MS_VIDEO_SIZE_CIF_H; s->bitrate=256000; s->frame_count = 0; s->cfg.g_w = s->width; s->cfg.g_h = s->height; /* encoder automatically places keyframes */ s->cfg.kf_mode = VPX_KF_AUTO; s->cfg.kf_max_dist = 300; s->cfg.rc_target_bitrate = ((float)s->bitrate)*0.92/1024.0; //0.9=take into account IP/UDP/RTP overhead, in average. s->cfg.g_pass = VPX_RC_ONE_PASS; /* -p 1 */ s->fps=15; s->cfg.g_timebase.num = 1; s->cfg.g_timebase.den = s->fps; s->cfg.rc_end_usage = VPX_CBR; /* --end-usage=cbr */ s->cfg.g_threads = ms_get_cpu_count(); ms_message("VP8 g_threads=%d", s->cfg.g_threads); s->cfg.rc_undershoot_pct = 95; /* --undershoot-pct=95 */ s->cfg.g_error_resilient = 1; s->cfg.g_lag_in_frames = 0; s->mtu=ms_get_payload_max_size()-1;/*-1 for the vp8 payload header*/ f->data = s; }