void krad_vpx_decoder_decode (krad_vpx_decoder_t *vpx, void *buffer, int len) { if (vpx_codec_decode (&vpx->decoder, buffer, len, 0, 0)) { printf ("Failed to decode %d byte frame: %s\n", len, vpx_codec_error (&vpx->decoder)); } if (vpx->width == 0) { vpx_codec_get_stream_info (&vpx->decoder, &vpx->stream_info); printf ("VPX Stream Info: W:%d H:%d KF:%d\n", vpx->stream_info.w, vpx->stream_info.h, vpx->stream_info.is_kf); vpx->width = vpx->stream_info.w; vpx->height = vpx->stream_info.h; } vpx->iter = NULL; vpx->img = vpx_codec_get_frame (&vpx->decoder, &vpx->iter); }
void krad_vpx_decoder_decode (krad_vpx_decoder_t *kradvpx, void *buffer, int len) { if (vpx_codec_decode(&kradvpx->decoder, buffer, len, 0, 0)) { failfast ("Failed to decode %d byte frame: %s\n", len, vpx_codec_error(&kradvpx->decoder)); //exit(1); } vpx_codec_get_stream_info (&kradvpx->decoder, &kradvpx->stream_info); //printf("VPX Stream Info: W:%d H:%d KF:%d\n", kradvpx->stream_info.w, kradvpx->stream_info.h, // kradvpx->stream_info.is_kf); if (kradvpx->width == 0) { kradvpx->width = kradvpx->stream_info.w; kradvpx->height = kradvpx->stream_info.h; } /* if (kradvpx->img == NULL) { kradvpx->width = kradvpx->stream_info.w; kradvpx->height = kradvpx->stream_info.h; if ((kradvpx->img = vpx_img_alloc(NULL, VPX_IMG_FMT_YV12, kradvpx->stream_info.w, kradvpx->stream_info.h, 1)) == NULL) { failfast ("Failed to allocate vpx image\n"); } } */ kradvpx->iter = NULL; kradvpx->img = vpx_codec_get_frame (&kradvpx->decoder, &kradvpx->iter); }
static void die_codec(vpx_codec_ctx_t *ctx, const char *s) { const char *detail = vpx_codec_error_detail(ctx); printf("%s: %s\n", s, vpx_codec_error(ctx)); if (detail) printf(" %s\n", detail); exit(EXIT_FAILURE); }
static void codec_error(vpx_codec_ctx_t *ctx, const char *s) { printf("%s: %s\n", s, vpx_codec_error(ctx)); return; //const char *detail = vpx_codec_error_detail(ctx); //if (detail) // printf(" %s\n", detail); }
static void die_codec(vpx_codec_ctx_t *ctx, const char *s) { // const char *detail = vpx_codec_error_detail(ctx); // // printf("%s: %s\n", s, vpx_codec_error(ctx)); // if(detail) // printf(" %s\n",detail); // exit(EXIT_FAILURE); // } //
int32_t kr_vpx_decode (krad_vpx_decoder_t *vpx, kr_medium_t *medium, kr_codeme_t *codeme) { if (vpx_codec_decode (&vpx->decoder, codeme->data, codeme->sz, 0, 0)) { printf ("Failed to decode %zu byte frame: %s\n", codeme->sz, vpx_codec_error (&vpx->decoder)); } if (vpx->width == 0) { vpx_codec_get_stream_info (&vpx->decoder, &vpx->stream_info); printk ("VPX Stream Info: W:%d H:%d KF:%d\n", vpx->stream_info.w, vpx->stream_info.h, vpx->stream_info.is_kf); vpx->width = vpx->stream_info.w; vpx->height = vpx->stream_info.h; } vpx->iter = NULL; vpx->img = vpx_codec_get_frame (&vpx->decoder, &vpx->iter); if (vpx->img != NULL) { medium->v.pps[0] = vpx->width; medium->v.pps[1] = vpx->width/2; medium->v.pps[2] = vpx->width/2; //printf ("VPXDEC: s %u %u %u", vpx->img->stride[0], vpx->img->stride[1], vpx->img->stride[2]); //memcpy (medium->data, vpx->img->img_data, vpx->img->stride[0] * vpx->height + (vpx->img->stride[1] * vpx->height * 2)); int r; for (r = 0; r< vpx->height; r++) { memcpy (medium->data + (r * vpx->width), vpx->img->planes[0] + (r * vpx->img->stride[0]), vpx->width); } for (r = 0; r< vpx->height/2; r++) { memcpy (medium->data + (vpx->width * (vpx->height)) + (r * vpx->width/2), vpx->img->planes[1] + (r * vpx->img->stride[1]), vpx->width / 2); } for (r = 0; r< vpx->height/2; r++) { memcpy (medium->data + (vpx->width * (vpx->height)) + ((vpx->width * (vpx->height))/4) + (r * vpx->width/2), vpx->img->planes[2] + (r * vpx->img->stride[2]), vpx->width / 2); } //memcpy (medium->data + vpx->img->stride[0] * vpx->height, vpx->img->planes[1], vpx->img->stride[1] * vpx->height / 2); //memcpy (medium->data + (vpx->img->stride[0] * vpx->height) + (vpx->img->stride[1] * (vpx->height /2)), vpx->img->planes[2], vpx->img->stride[2] * vpx->height / 2); medium->v.ppx[0] = medium->data; medium->v.ppx[1] = medium->data + vpx->width * (vpx->height); medium->v.ppx[2] = medium->data + vpx->width * (vpx->height) + ((vpx->width * (vpx->height)) /4); return 1; } return 0; }
void WebmExporter::codec_error(const std::string& s) { auto detail = vpx_codec_error_detail(&_codec); std::cerr << s << ": " << vpx_codec_error(&_codec); if (detail) { std::cerr << ": " << detail; } std::cerr << std::endl; }
static void krad_vpx_fail (vpx_codec_ctx_t *ctx, const char *s) { const char *detail = vpx_codec_error_detail(ctx); printke ("%s: %s\n", s, vpx_codec_error(ctx)); if (detail) { printke ("%s\n", detail); } failfast (""); }
static void krad_vpx_fail (vpx_codec_ctx_t *ctx, const char *msg) { const char *err_details; err_details = vpx_codec_error_detail (ctx); if (err_details == NULL) { err_details = "None"; } printf ("Krad VPX Fail: %s %s\nDetail: %s", msg, vpx_codec_error (ctx), err_details); }
// Decodes any frame that was parsed by FFmpeg static int vpx_decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *pkt) { Decoder * const decoder = avctx->opaque; AVFrame * const frame = data; const void *iter; struct vpx_image *img; vpx_codec_err_t err; int i; err = vpx_codec_decode(&decoder->decoder, pkt->data, pkt->size, NULL, 0); if (err != VPX_CODEC_OK) goto error_decode; iter = NULL; img = vpx_codec_get_frame(&decoder->decoder, &iter); if (img) { frame->format = ff_get_pix_fmt(img->fmt); if (frame->format == AV_PIX_FMT_NONE || frame->format != avctx->pix_fmt) goto error_unsupported_format; frame->width = img->d_w; frame->height = img->d_h; if (frame->width != avctx->width || frame->height != avctx->height) { avcodec_set_dimensions(avctx, frame->width, frame->height); if (frame->width != avctx->width || frame->height != avctx->height) goto error_size_change; } frame->interlaced_frame = 0; for (i = 0; i < 4; i++) { frame->data[i] = img->planes[i]; frame->linesize[i] = img->stride[i]; } *got_frame = 1; } return pkt->size; /* ERRORS */ error_decode: mvt_error("failed to decode frame: %s", vpx_codec_error(&decoder->decoder)); return AVERROR_INVALIDDATA; error_unsupported_format: mvt_error("unsupported image format (%d)", img->fmt); return AVERROR_INVALIDDATA; error_size_change: mvt_error("failed to change dimensions (%dx%d)", frame->width, frame->height); return AVERROR_INVALIDDATA; }
static void ctx_exit_on_error(vpx_codec_ctx_t *ctx, const char *s) { if (ctx->err) { const char *detail = vpx_codec_error_detail(ctx); fprintf(stderr, "%s: %s\n", s, vpx_codec_error(ctx)); if (detail) fprintf(stderr, " %s\n", detail); exit(EXIT_FAILURE); } }
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; }
struct DecInputContext load(char const *filename) { FILE *infile; const VpxInterface *interface = NULL; vpx_codec_dec_cfg_t cfg = {0, 0, 0}; int dec_flags = 0; infile = fopen(filename, "rb"); if (!infile) { fatal("Failed to open file '%s'", filename); } struct DecInputContext input; vpx_codec_ctx_t *decoder = (vpx_codec_ctx_t*)calloc(1, sizeof(vpx_codec_ctx_t));; struct VpxInputContext *vpx_ctx = (VpxInputContext*)calloc(1, sizeof(VpxInputContext)); struct WebmInputContext *webm_ctx = (WebmInputContext*)calloc(1, sizeof(WebmInputContext)); memset(&(input), 0, sizeof(input)); input.vpx_ctx = vpx_ctx; input.webm_ctx = webm_ctx; input.decoder = decoder; input.file = infile; input.vpx_ctx->file = infile; if(file_is_webm(input.webm_ctx, input.vpx_ctx)) input.vpx_ctx->file_type = FILE_TYPE_WEBM; else fatal("Input isn't a webm!"); if(webm_guess_framerate(input.webm_ctx, input.vpx_ctx)) { fatal("Failed to guess framerate!"); } interface = get_vpx_decoder_by_fourcc(input.vpx_ctx->fourcc); if(!interface) interface = get_vpx_decoder_by_index(0); if(vpx_codec_dec_init(input.decoder, interface->codec_interface(), &cfg, dec_flags)) { fatal("Failed to initialize decoder: %s\n", vpx_codec_error(input.decoder)); } return input; }
// Initializes VPX decoder static int vpx_init(AVCodecContext *avctx, const struct vpx_codec_iface *iface) { Decoder * const decoder = avctx->opaque; vpx_codec_err_t err; memset(&decoder->config, 0, sizeof(decoder->config)); decoder->config.threads = MVT_MIN(avctx->thread_count, 16); err = vpx_codec_dec_init(&decoder->decoder, iface, &decoder->config, 0); if (err != VPX_CODEC_OK) goto error_init_decoder; decoder->is_open = true; avctx->pix_fmt = AV_PIX_FMT_YUV420P; return 0; /* ERRORS */ error_init_decoder: mvt_error("failed to initialize decoder: %s", vpx_codec_error(&decoder->decoder)); return AVERROR(EINVAL); }
static void close_video(video_context *video_ctx) { if(vpx_codec_destroy(&(video_ctx->vpx_ctx))) { printf("Warning: failed to destroy libvpx context: %s\n", vpx_codec_error(&video_ctx->vpx_ctx)); } if(video_ctx->packet_queue) { while(video_ctx->packet_queue && video_ctx->packet_queue->size) { nestegg_packet *packet = queue_get(video_ctx->packet_queue); if(packet) nestegg_free_packet(packet); } queue_destroy(video_ctx->packet_queue); } if(video_ctx->frame_queue) { while(video_ctx->frame_queue && video_ctx->frame_queue->size) { yuv_frame_destroy((yuv_frame *) queue_get(video_ctx->frame_queue)); } queue_destroy(video_ctx->frame_queue); } }
static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_frame_t *frame) { vpx_context_t *context = (vpx_context_t *)codec->private_info; int width = 0; int height = 0; uint32_t dur; int64_t pts; vpx_enc_frame_flags_t vpx_flags = 0; switch_time_t now; int err; if (frame->flags & SFF_SAME_IMAGE) { return consume_partition(context, frame); } if (context->need_encoder_reset != 0) { reset_codec_encoder(codec); context->need_encoder_reset = 0; } if (frame->img->d_h > 1) { width = frame->img->d_w; height = frame->img->d_h; } else { width = frame->img->w; height = frame->img->h; } if (context->config.g_w != width || context->config.g_h != height) { context->codec_settings.video.width = width; context->codec_settings.video.height = height; reset_codec_encoder(codec); frame->flags |= SFF_PICTURE_RESET; context->need_key_frame = 1; } if (!context->encoder_init) { init_encoder(codec); } if (context->change_bandwidth) { context->codec_settings.video.bandwidth = context->change_bandwidth; context->change_bandwidth = 0; init_encoder(codec); } now = switch_time_now(); if (context->need_key_frame != 0) { // force generate a key frame if (!context->last_key_frame || (now - context->last_key_frame) > KEY_FRAME_MIN_FREQ) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "VPX KEYFRAME GENERATED\n"); vpx_flags |= VPX_EFLAG_FORCE_KF; context->need_key_frame = 0; context->last_key_frame = now; } } context->framecount++; pts = (now - context->start_time) / 1000; dur = context->last_ms ? (now - context->last_ms) / 1000 : pts; if ((err = vpx_codec_encode(&context->encoder, (vpx_image_t *) frame->img, pts, dur, vpx_flags, VPX_DL_REALTIME)) != VPX_CODEC_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VPX encode error %d:%s:%s\n", err, vpx_codec_error(&context->encoder), vpx_codec_error_detail(&context->encoder)); frame->datalen = 0; return SWITCH_STATUS_FALSE; } context->enc_iter = NULL; context->last_ts = frame->timestamp; context->last_ms = now; return consume_partition(context, frame); }
Dynamic read_frame(struct DecInputContext *input) { vpx_codec_iter_t iter = NULL; vpx_image_t *img; uint8_t *buf = NULL; size_t bytes_in_buffer = 0; size_t buffer_size = 0; int status = webm_read_frame(input->webm_ctx, &buf, &bytes_in_buffer, &buffer_size); if(status == 0) { if(vpx_codec_decode(input->decoder, buf, (unsigned int)bytes_in_buffer, NULL, 0)) { warn("Failed to decode frame: %s", vpx_codec_error(input->decoder)); } } else { warn("EOF/Error %d", status); } if(status == 0) { img = vpx_codec_get_frame(input->decoder, &iter); } else { img = NULL; } /* { status:Int, (0 = success, 1 = EOF, -1 = Error) data:BytesData, // image bytes width:Int, height:Int, comp:Int, // RGBA = 4 } */ int width = 0; int height = 0; int comp = 4; unsigned char* rgba; hx::Anon result = hx::Anon_obj::Create(); result->Add(HX_CSTRING("status"), status); if(img != NULL) { width = img->d_w; height = img->d_h; rgba = (unsigned char*)malloc(sizeof(unsigned char) * width * height * comp); if(img->fmt == VPX_IMG_FMT_I420) { ::libyuv::I420ToABGR( img->planes[VPX_PLANE_Y],img->stride[VPX_PLANE_Y], img->planes[VPX_PLANE_U],img->stride[VPX_PLANE_U], img->planes[VPX_PLANE_V],img->stride[VPX_PLANE_V], rgba, width * comp, width, height ); ImgBytesData data = to_haxe_bytes(rgba, width * height * comp); result->Add(HX_CSTRING("data"), data); } else { warn("Img format unknown"); } } else { warn("No image decoded!"); } result->Add(HX_CSTRING("width"), width); result->Add(HX_CSTRING("height"), height); result->Add(HX_CSTRING("comp"), comp); return result; }
/**************************************************************************** * Decode: the whole thing ****************************************************************************/ static picture_t *Decode(decoder_t *dec, block_t **pp_block) { struct vpx_codec_ctx *ctx = &dec->p_sys->ctx; block_t *block = *pp_block; if (!block) return NULL; if (block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) return NULL; /* Associate packet PTS with decoded frame */ mtime_t *pkt_pts = malloc(sizeof(*pkt_pts)); if (!pkt_pts) { block_Release(block); *pp_block = NULL; return NULL; } *pkt_pts = block->i_pts; vpx_codec_err_t err; err = vpx_codec_decode(ctx, block->p_buffer, block->i_buffer, pkt_pts, 0); block_Release(block); *pp_block = NULL; if (err != VPX_CODEC_OK) { free(pkt_pts); const char *error = vpx_codec_error(ctx); const char *detail = vpx_codec_error_detail(ctx); if (!detail) detail = "no specific information"; msg_Err(dec, "Failed to decode frame: %s (%s)", error, detail); return NULL; } const void *iter = NULL; struct vpx_image *img = vpx_codec_get_frame(ctx, &iter); if (!img) { free(pkt_pts); return NULL; } /* fetches back the PTS */ pkt_pts = img->user_priv; mtime_t pts = *pkt_pts; free(pkt_pts); if (img->fmt != VPX_IMG_FMT_I420) { msg_Err(dec, "Unsupported output colorspace %d", img->fmt); return NULL; } video_format_t *v = &dec->fmt_out.video; if (img->d_w != v->i_visible_width || img->d_h != v->i_visible_height) { v->i_visible_width = img->d_w; v->i_visible_height = img->d_h; } picture_t *pic = decoder_NewPicture(dec); if (!pic) return NULL; for (int plane = 0; plane < pic->i_planes; plane++ ) { uint8_t *src = img->planes[plane]; uint8_t *dst = pic->p[plane].p_pixels; int src_stride = img->stride[plane]; int dst_stride = pic->p[plane].i_pitch; int size = __MIN( src_stride, dst_stride ); for( int line = 0; line < pic->p[plane].i_visible_lines; line++ ) { memcpy( dst, src, size ); src += src_stride; dst += dst_stride; } } pic->b_progressive = true; /* codec does not support interlacing */ pic->date = pts; return pic; }
/***************************************************************************** * 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); }
int main_loop(int argc, const char **argv_) { vpx_codec_ctx_t decoder; char *fn = NULL; int i; uint8_t *buf = NULL; size_t bytes_in_buffer = 0, buffer_size = 0; FILE *infile; int frame_in = 0, frame_out = 0, flipuv = 0, noblit = 0; int do_md5 = 0, progress = 0; int stop_after = 0, postproc = 0, summary = 0, quiet = 1; int arg_skip = 0; int ec_enabled = 0; const VpxInterface *interface = NULL; const VpxInterface *fourcc_interface = NULL; uint64_t dx_time = 0; struct arg arg; char **argv, **argi, **argj; int single_file; int use_y4m = 1; vpx_codec_dec_cfg_t cfg = {0}; #if CONFIG_VP8_DECODER vp8_postproc_cfg_t vp8_pp_cfg = {0}; int vp8_dbg_color_ref_frame = 0; int vp8_dbg_color_mb_modes = 0; int vp8_dbg_color_b_modes = 0; int vp8_dbg_display_mv = 0; #endif int frames_corrupted = 0; int dec_flags = 0; int do_scale = 0; vpx_image_t *scaled_img = NULL; int frame_avail, got_data; int num_external_frame_buffers = 0; struct ExternalFrameBufferList ext_fb_list = {0}; const char *outfile_pattern = NULL; char outfile_name[PATH_MAX] = {0}; FILE *outfile = NULL; MD5Context md5_ctx; unsigned char md5_digest[16]; struct VpxDecInputContext input = {0}; struct VpxInputContext vpx_input_ctx = {0}; struct WebmInputContext webm_ctx = {0}; input.vpx_input_ctx = &vpx_input_ctx; input.webm_ctx = &webm_ctx; /* Parse command line */ exec_name = argv_[0]; argv = argv_dup(argc - 1, argv_ + 1); for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) { memset(&arg, 0, sizeof(arg)); arg.argv_step = 1; if (arg_match(&arg, &codecarg, argi)) { interface = get_vpx_decoder_by_name(arg.val); if (!interface) die("Error: Unrecognized argument (%s) to --codec\n", arg.val); } else if (arg_match(&arg, &looparg, argi)) { // no-op } else if (arg_match(&arg, &outputfile, argi)) outfile_pattern = arg.val; else if (arg_match(&arg, &use_yv12, argi)) { use_y4m = 0; flipuv = 1; } else if (arg_match(&arg, &use_i420, argi)) { use_y4m = 0; flipuv = 0; } else if (arg_match(&arg, &flipuvarg, argi)) flipuv = 1; else if (arg_match(&arg, &noblitarg, argi)) noblit = 1; else if (arg_match(&arg, &progressarg, argi)) progress = 1; else if (arg_match(&arg, &limitarg, argi)) stop_after = arg_parse_uint(&arg); else if (arg_match(&arg, &skiparg, argi)) arg_skip = arg_parse_uint(&arg); else if (arg_match(&arg, &postprocarg, argi)) postproc = 1; else if (arg_match(&arg, &md5arg, argi)) do_md5 = 1; else if (arg_match(&arg, &summaryarg, argi)) summary = 1; else if (arg_match(&arg, &threadsarg, argi)) cfg.threads = arg_parse_uint(&arg); else if (arg_match(&arg, &verbosearg, argi)) quiet = 0; else if (arg_match(&arg, &scalearg, argi)) do_scale = 1; else if (arg_match(&arg, &fb_arg, argi)) num_external_frame_buffers = arg_parse_uint(&arg); #if CONFIG_VP8_DECODER else if (arg_match(&arg, &addnoise_level, argi)) { postproc = 1; vp8_pp_cfg.post_proc_flag |= VP8_ADDNOISE; vp8_pp_cfg.noise_level = arg_parse_uint(&arg); } else if (arg_match(&arg, &demacroblock_level, argi)) { postproc = 1; vp8_pp_cfg.post_proc_flag |= VP8_DEMACROBLOCK; vp8_pp_cfg.deblocking_level = arg_parse_uint(&arg); } else if (arg_match(&arg, &deblock, argi)) { postproc = 1; vp8_pp_cfg.post_proc_flag |= VP8_DEBLOCK; } else if (arg_match(&arg, &mfqe, argi)) { postproc = 1; vp8_pp_cfg.post_proc_flag |= VP8_MFQE; } else if (arg_match(&arg, &pp_debug_info, argi)) { unsigned int level = arg_parse_uint(&arg); postproc = 1; vp8_pp_cfg.post_proc_flag &= ~0x7; if (level) vp8_pp_cfg.post_proc_flag |= level; } else if (arg_match(&arg, &pp_disp_ref_frame, argi)) { unsigned int flags = arg_parse_int(&arg); if (flags) { postproc = 1; vp8_dbg_color_ref_frame = flags; } } else if (arg_match(&arg, &pp_disp_mb_modes, argi)) { unsigned int flags = arg_parse_int(&arg); if (flags) { postproc = 1; vp8_dbg_color_mb_modes = flags; } } else if (arg_match(&arg, &pp_disp_b_modes, argi)) { unsigned int flags = arg_parse_int(&arg); if (flags) { postproc = 1; vp8_dbg_color_b_modes = flags; } } else if (arg_match(&arg, &pp_disp_mvs, argi)) { unsigned int flags = arg_parse_int(&arg); if (flags) { postproc = 1; vp8_dbg_display_mv = flags; } } else if (arg_match(&arg, &error_concealment, argi)) { ec_enabled = 1; } #endif else argj++; } /* Check for unrecognized options */ for (argi = argv; *argi; argi++) if (argi[0][0] == '-' && strlen(argi[0]) > 1) die("Error: Unrecognized option %s\n", *argi); /* Handle non-option arguments */ fn = argv[0]; if (!fn) usage_exit(); /* Open file */ infile = strcmp(fn, "-") ? fopen(fn, "rb") : set_binary_mode(stdin); if (!infile) { fprintf(stderr, "Failed to open file '%s'", strcmp(fn, "-") ? fn : "stdin"); return EXIT_FAILURE; } #if CONFIG_OS_SUPPORT /* Make sure we don't dump to the terminal, unless forced to with -o - */ if (!outfile_pattern && isatty(fileno(stdout)) && !do_md5 && !noblit) { fprintf(stderr, "Not dumping raw video to your terminal. Use '-o -' to " "override.\n"); return EXIT_FAILURE; } #endif input.vpx_input_ctx->file = infile; if (file_is_ivf(input.vpx_input_ctx)) input.vpx_input_ctx->file_type = FILE_TYPE_IVF; #if CONFIG_WEBM_IO else if (file_is_webm(input.webm_ctx, input.vpx_input_ctx)) input.vpx_input_ctx->file_type = FILE_TYPE_WEBM; #endif else if (file_is_raw(input.vpx_input_ctx)) input.vpx_input_ctx->file_type = FILE_TYPE_RAW; else { fprintf(stderr, "Unrecognized input file type.\n"); #if !CONFIG_WEBM_IO fprintf(stderr, "vpxdec was built without WebM container support.\n"); #endif return EXIT_FAILURE; } outfile_pattern = outfile_pattern ? outfile_pattern : "-"; single_file = is_single_file(outfile_pattern); if (!noblit && single_file) { generate_filename(outfile_pattern, outfile_name, PATH_MAX, vpx_input_ctx.width, vpx_input_ctx.height, 0); if (do_md5) MD5Init(&md5_ctx); else outfile = open_outfile(outfile_name); } if (use_y4m && !noblit) { if (!single_file) { fprintf(stderr, "YUV4MPEG2 not supported with output patterns," " try --i420 or --yv12.\n"); return EXIT_FAILURE; } #if CONFIG_WEBM_IO if (vpx_input_ctx.file_type == FILE_TYPE_WEBM) { if (webm_guess_framerate(input.webm_ctx, input.vpx_input_ctx)) { fprintf(stderr, "Failed to guess framerate -- error parsing " "webm file?\n"); return EXIT_FAILURE; } } #endif } fourcc_interface = get_vpx_decoder_by_fourcc(vpx_input_ctx.fourcc); if (interface && fourcc_interface && interface != fourcc_interface) warn("Header indicates codec: %s\n", fourcc_interface->name); else interface = fourcc_interface; if (!interface) interface = get_vpx_decoder_by_index(0); dec_flags = (postproc ? VPX_CODEC_USE_POSTPROC : 0) | (ec_enabled ? VPX_CODEC_USE_ERROR_CONCEALMENT : 0); if (vpx_codec_dec_init(&decoder, interface->interface(), &cfg, dec_flags)) { fprintf(stderr, "Failed to initialize decoder: %s\n", vpx_codec_error(&decoder)); return EXIT_FAILURE; } if (!quiet) fprintf(stderr, "%s\n", decoder.name); #if CONFIG_VP8_DECODER if (vp8_pp_cfg.post_proc_flag && vpx_codec_control(&decoder, VP8_SET_POSTPROC, &vp8_pp_cfg)) { fprintf(stderr, "Failed to configure postproc: %s\n", vpx_codec_error(&decoder)); return EXIT_FAILURE; } if (vp8_dbg_color_ref_frame && vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_REF_FRAME, vp8_dbg_color_ref_frame)) { fprintf(stderr, "Failed to configure reference block visualizer: %s\n", vpx_codec_error(&decoder)); return EXIT_FAILURE; } if (vp8_dbg_color_mb_modes && vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_MB_MODES, vp8_dbg_color_mb_modes)) { fprintf(stderr, "Failed to configure macro block visualizer: %s\n", vpx_codec_error(&decoder)); return EXIT_FAILURE; } if (vp8_dbg_color_b_modes && vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_B_MODES, vp8_dbg_color_b_modes)) { fprintf(stderr, "Failed to configure block visualizer: %s\n", vpx_codec_error(&decoder)); return EXIT_FAILURE; } if (vp8_dbg_display_mv && vpx_codec_control(&decoder, VP8_SET_DBG_DISPLAY_MV, vp8_dbg_display_mv)) { fprintf(stderr, "Failed to configure motion vector visualizer: %s\n", vpx_codec_error(&decoder)); return EXIT_FAILURE; } #endif if (arg_skip) fprintf(stderr, "Skipping first %d frames.\n", arg_skip); while (arg_skip) { if (read_frame(&input, &buf, &bytes_in_buffer, &buffer_size)) break; arg_skip--; } if (num_external_frame_buffers > 0) { ext_fb_list.num_external_frame_buffers = num_external_frame_buffers; ext_fb_list.ext_fb = (struct ExternalFrameBuffer *)calloc( num_external_frame_buffers, sizeof(*ext_fb_list.ext_fb)); if (vpx_codec_set_frame_buffer_functions( &decoder, get_vp9_frame_buffer, release_vp9_frame_buffer, &ext_fb_list)) { fprintf(stderr, "Failed to configure external frame buffers: %s\n", vpx_codec_error(&decoder)); return EXIT_FAILURE; } } frame_avail = 1; got_data = 0; /* Decode file */ while (frame_avail || got_data) { vpx_codec_iter_t iter = NULL; vpx_image_t *img; struct vpx_usec_timer timer; int corrupted; frame_avail = 0; if (!stop_after || frame_in < stop_after) { if (!read_frame(&input, &buf, &bytes_in_buffer, &buffer_size)) { frame_avail = 1; frame_in++; vpx_usec_timer_start(&timer); if (vpx_codec_decode(&decoder, buf, (unsigned int)bytes_in_buffer, NULL, 0)) { const char *detail = vpx_codec_error_detail(&decoder); warn("Failed to decode frame %d: %s", frame_in, vpx_codec_error(&decoder)); if (detail) warn("Additional information: %s", detail); goto fail; } vpx_usec_timer_mark(&timer); dx_time += vpx_usec_timer_elapsed(&timer); } } vpx_usec_timer_start(&timer); got_data = 0; if ((img = vpx_codec_get_frame(&decoder, &iter))) { ++frame_out; got_data = 1; } vpx_usec_timer_mark(&timer); dx_time += (unsigned int)vpx_usec_timer_elapsed(&timer); if (vpx_codec_control(&decoder, VP8D_GET_FRAME_CORRUPTED, &corrupted)) { warn("Failed VP8_GET_FRAME_CORRUPTED: %s", vpx_codec_error(&decoder)); goto fail; } frames_corrupted += corrupted; if (progress) show_progress(frame_in, frame_out, dx_time); if (!noblit && img) { const int PLANES_YUV[] = {VPX_PLANE_Y, VPX_PLANE_U, VPX_PLANE_V}; const int PLANES_YVU[] = {VPX_PLANE_Y, VPX_PLANE_V, VPX_PLANE_U}; const int *planes = flipuv ? PLANES_YVU : PLANES_YUV; if (do_scale) { if (frame_out == 1) { // If the output frames are to be scaled to a fixed display size then // use the width and height specified in the container. If either of // these is set to 0, use the display size set in the first frame // header. If that is unavailable, use the raw decoded size of the // first decoded frame. int display_width = vpx_input_ctx.width; int display_height = vpx_input_ctx.height; if (!display_width || !display_height) { int display_size[2]; if (vpx_codec_control(&decoder, VP9D_GET_DISPLAY_SIZE, display_size)) { // As last resort use size of first frame as display size. display_width = img->d_w; display_height = img->d_h; } else { display_width = display_size[0]; display_height = display_size[1]; } } scaled_img = vpx_img_alloc(NULL, VPX_IMG_FMT_I420, display_width, display_height, 16); } if (img->d_w != scaled_img->d_w || img->d_h != scaled_img->d_h) { vpx_image_scale(img, scaled_img, kFilterBox); img = scaled_img; } } if (single_file) { if (use_y4m) { char buf[Y4M_BUFFER_SIZE] = {0}; size_t len = 0; if (frame_out == 1) { // Y4M file header len = y4m_write_file_header(buf, sizeof(buf), vpx_input_ctx.width, vpx_input_ctx.height, &vpx_input_ctx.framerate, img->fmt); if (do_md5) { MD5Update(&md5_ctx, (md5byte *)buf, (unsigned int)len); } else { fputs(buf, outfile); } } // Y4M frame header len = y4m_write_frame_header(buf, sizeof(buf)); if (do_md5) { MD5Update(&md5_ctx, (md5byte *)buf, (unsigned int)len); } else { fputs(buf, outfile); } } if (do_md5) { update_image_md5(img, planes, &md5_ctx); } else { write_image_file(img, planes, outfile); } } else { generate_filename(outfile_pattern, outfile_name, PATH_MAX, img->d_w, img->d_h, frame_in); if (do_md5) { MD5Init(&md5_ctx); update_image_md5(img, planes, &md5_ctx); MD5Final(md5_digest, &md5_ctx); print_md5(md5_digest, outfile_name); } else { outfile = open_outfile(outfile_name); write_image_file(img, planes, outfile); fclose(outfile); } } } if (stop_after && frame_in >= stop_after) break; } if (summary || progress) { show_progress(frame_in, frame_out, dx_time); fprintf(stderr, "\n"); } if (frames_corrupted) fprintf(stderr, "WARNING: %d frames corrupted.\n", frames_corrupted); fail: if (vpx_codec_destroy(&decoder)) { fprintf(stderr, "Failed to destroy decoder: %s\n", vpx_codec_error(&decoder)); return EXIT_FAILURE; } if (!noblit && single_file) { if (do_md5) { MD5Final(md5_digest, &md5_ctx); print_md5(md5_digest, outfile_name); } else { fclose(outfile); } } #if CONFIG_WEBM_IO if (input.vpx_input_ctx->file_type == FILE_TYPE_WEBM) webm_free(input.webm_ctx); #endif if (input.vpx_input_ctx->file_type != FILE_TYPE_WEBM) free(buf); if (scaled_img) vpx_img_free(scaled_img); for (i = 0; i < ext_fb_list.num_external_frame_buffers; ++i) { free(ext_fb_list.ext_fb[i].data); } free(ext_fb_list.ext_fb); fclose(infile); free(argv); return frames_corrupted ? EXIT_FAILURE : EXIT_SUCCESS; }
add_submodule() set_shortname("vpx") set_capability("encoder", 60) set_description(N_("WebM video encoder")) set_callbacks(OpenEncoder, CloseEncoder) # define ENC_CFG_PREFIX "sout-vpx-" add_integer( ENC_CFG_PREFIX "quality-mode", VPX_DL_GOOD_QUALITY, QUALITY_MODE_TEXT, QUALITY_MODE_LONGTEXT, true ) change_integer_range( 0, 2 ) #endif vlc_module_end () static void vpx_err_msg(vlc_object_t *this, struct vpx_codec_ctx *ctx, const char *msg) { const char *error = vpx_codec_error(ctx); const char *detail = vpx_codec_error_detail(ctx); if (!detail) detail = "no specific information"; msg_Err(this, msg, error, detail); } #define VPX_ERR(this, ctx, msg) vpx_err_msg(VLC_OBJECT(this), ctx, msg ": %s (%s)") /***************************************************************************** * decoder_sys_t: libvpx decoder descriptor *****************************************************************************/ struct decoder_sys_t { struct vpx_codec_ctx ctx; };
static switch_status_t switch_vpx_decode(switch_codec_t *codec, switch_frame_t *frame) { vpx_context_t *context = (vpx_context_t *)codec->private_info; switch_size_t len; vpx_codec_ctx_t *decoder = NULL; switch_status_t status = SWITCH_STATUS_SUCCESS; int is_start = 0, is_keyframe = 0, get_refresh = 0; if (context->is_vp9) { is_start = is_keyframe = IS_VP9_KEY_FRAME(*(unsigned char *)frame->data); } else { // vp8 is_start = (*(unsigned char *)frame->data & 0x10); is_keyframe = IS_VP8_KEY_FRAME((uint8_t *)frame->data); } // if (is_keyframe) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "got key %d\n", is_keyframe); if (context->need_decoder_reset != 0) { vpx_codec_destroy(&context->decoder); context->decoder_init = 0; init_decoder(codec); context->need_decoder_reset = 0; } if (!context->decoder_init) { init_decoder(codec); } if (!context->decoder_init) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "VPX decoder is not initialized!\n"); return SWITCH_STATUS_FALSE; } decoder = &context->decoder; // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "len: %d ts: %u mark:%d\n", frame->datalen, frame->timestamp, frame->m); // context->last_received_timestamp = frame->timestamp; context->last_received_complete_picture = frame->m ? SWITCH_TRUE : SWITCH_FALSE; if (is_start) { context->got_start_frame = 1; } if (is_keyframe) { if (context->got_key_frame <= 0) { context->got_key_frame = 1; if (!is_keyframe) { get_refresh = 1; } } else { context->got_key_frame++; } } else if (context->got_key_frame <= 0) { if ((--context->got_key_frame % 200) == 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Waiting for key frame %d\n", context->got_key_frame); } if (!context->got_start_frame) { switch_goto_status(SWITCH_STATUS_MORE_DATA, end); } } status = context->is_vp9 ? buffer_vp9_packets(context, frame) : buffer_vp8_packets(context, frame); if (context->dec_iter && (frame->img = (switch_image_t *) vpx_codec_get_frame(decoder, &context->dec_iter))) { switch_goto_status(SWITCH_STATUS_SUCCESS, end); } //printf("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); len = switch_buffer_inuse(context->vpx_packet_buffer); //if (frame->m && (status != SWITCH_STATUS_SUCCESS || !len)) { //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "WTF????? %d %ld\n", status, len); //} if (status == SWITCH_STATUS_SUCCESS && frame->m && len) { uint8_t *data; int corrupted = 0; int err; switch_buffer_peek_zerocopy(context->vpx_packet_buffer, (void *)&data); context->dec_iter = NULL; err = vpx_codec_decode(decoder, data, (unsigned int)len, NULL, 0); if (err != VPX_CODEC_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Error decoding %" SWITCH_SIZE_T_FMT " bytes, [%d:%s:%s]\n", len, err, vpx_codec_error(decoder), vpx_codec_error_detail(decoder)); switch_goto_status(SWITCH_STATUS_RESTART, end); } if (vpx_codec_control(decoder, VP8D_GET_FRAME_CORRUPTED, &corrupted) != VPX_CODEC_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "VPX control error!\n"); switch_goto_status(SWITCH_STATUS_RESTART, end); } if (corrupted) { frame->img = NULL; } else { frame->img = (switch_image_t *) vpx_codec_get_frame(decoder, &context->dec_iter); } switch_buffer_zero(context->vpx_packet_buffer); if (!frame->img) { //context->need_decoder_reset = 1; context->got_key_frame = 0; context->got_start_frame = 0; status = SWITCH_STATUS_RESTART; } } end: if (status == SWITCH_STATUS_RESTART) { switch_buffer_zero(context->vpx_packet_buffer); //context->need_decoder_reset = 1; context->got_key_frame = 0; context->got_start_frame = 0; //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "RESET VPX\n"); } if (!frame->img || status == SWITCH_STATUS_RESTART) { status = SWITCH_STATUS_MORE_DATA; } if (context->got_key_frame <= 0 || get_refresh) { switch_set_flag(frame, SFF_WAIT_KEY_FRAME); } return status; }
int main(int argc, char **argv) { vpx_codec_ctx_t decoder; vpx_codec_iface_t *iface = ifaces[0].iface; vpx_codec_iter_t iter; vpx_codec_dec_cfg_t cfg; vpx_codec_err_t res = VPX_CODEC_OK; unsigned int alloc_sz = 0; unsigned int w = 352; unsigned int h = 288; int i; exec_name = argv[0]; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "--codec")) { if (i + 1 < argc) { int j, k = -1; i++; for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++) if (!strcmp(ifaces[j].name, argv[i])) k = j; if (k >= 0) iface = ifaces[k].iface; else usage_error("Error: Unrecognized argument (%s) to --codec\n", argv[i]); } else usage_error("Error: Option --codec requires argument.\n"); } else if (!strcmp(argv[i], "-v")) verbose = 1; else if (!strcmp(argv[i], "-h")) if (i + 1 < argc) { h = atoi(argv[++i]); } else usage_error("Error: Option -h requires argument.\n"); else if (!strcmp(argv[i], "-w")) if (i + 1 < argc) { w = atoi(argv[++i]); } else usage_error("Error: Option -w requires argument.\n"); else if (!strcmp(argv[i], "--help")) usage_exit(); else usage_error("Error: Unrecognized option %s\n\n", argv[i]); } if (argc == 1) printf("Using built-in defaults. For options, rerun with --help\n\n"); /* XMA mode is not supported on all decoders! */ if (!(vpx_codec_get_caps(iface) & VPX_CODEC_CAP_XMA)) { printf("%s does not support XMA mode!\n", vpx_codec_iface_name(iface)); return EXIT_FAILURE; } /* The codec knows how much memory to allocate based on the size of the * encoded frames. This data can be parsed from the bitstream with * vpx_codec_peek_stream_info() if a bitstream is available. Otherwise, * a fixed size can be used that will be the upper limit on the frame * size the decoder can decode. */ cfg.w = w; cfg.h = h; /* Initialize the decoder in XMA mode. */ if (vpx_codec_dec_init(&decoder, iface, &cfg, VPX_CODEC_USE_XMA)) { printf("Failed to initialize decoder in XMA mode: %s\n", vpx_codec_error(&decoder)); return EXIT_FAILURE; } /* Iterate through the list of memory maps, allocating them with the * requested alignment. */ iter = NULL; do { vpx_codec_mmap_t mmap; unsigned int align; res = vpx_codec_get_mem_map(&decoder, &mmap, &iter); align = mmap.align ? mmap.align - 1 : 0; if (!res) { if (verbose) printf("Allocating segment %u, size %lu, align %u %s\n", mmap.id, mmap.sz, mmap.align, mmap.flags & VPX_CODEC_MEM_ZERO ? "(ZEROED)" : ""); if (mmap.flags & VPX_CODEC_MEM_ZERO) mmap.priv = calloc(1, mmap.sz + align); else mmap.priv = malloc(mmap.sz + align); mmap.base = (void *)((((uintptr_t)mmap.priv) + align) & ~(uintptr_t)align); mmap.dtor = my_mem_dtor; alloc_sz += mmap.sz + align; if (vpx_codec_set_mem_map(&decoder, &mmap, 1)) { printf("Failed to set mmap: %s\n", vpx_codec_error(&decoder)); return EXIT_FAILURE; } } else if (res != VPX_CODEC_LIST_END) { printf("Failed to get mmap: %s\n", vpx_codec_error(&decoder)); return EXIT_FAILURE; } } while (res != VPX_CODEC_LIST_END); printf("%s\n %d bytes external memory required for %dx%d.\n", decoder.name, alloc_sz, cfg.w, cfg.h); vpx_codec_destroy(&decoder); return EXIT_SUCCESS; }
ComponentResult encodeThisSourceFrame(VP8EncoderGlobals glob, ICMCompressorSourceFrameRef sourceFrame) { vpx_codec_err_t codecError; ComponentResult err = noErr; const UInt8 *decoderDataPtr; int storageIndex = 0; //time is multiplied by 2 to allow space for altref frames UInt32 time2 = glob->frameCount * 2; dbg_printf("[vp8e - %08lx] encode this frame %08lx %ld time2 %lu\n", (UInt32)glob, (UInt32)sourceFrame, glob->frameCount, time2); //long dispNumber = ICMCompressorSourceFrameGetDisplayNumber(sourceFrame); // Initialize codec if needed initializeCodec(glob, sourceFrame); /////// Transfer the current frame to glob->raw if (sourceFrame != NULL) { if (glob->currentPass != VPX_RC_FIRST_PASS) addSourceFrame(glob,sourceFrame); err = convertColorSpace(glob, sourceFrame); if (err) goto bail; int flags = 0 ; //TODO - find out what I may need in these flags dbg_printf("[vp8e - %08lx] vpx_codec_encode codec %x raw %x framecount %d flags %x\n", (UInt32)glob, glob->codec, glob->raw, glob->frameCount, flags); //TODO seems like quality should be an option. Right now hardcoded to GOOD_QUALITY codecError = vpx_codec_encode(glob->codec, glob->raw, time2, 1, flags, VPX_DL_GOOD_QUALITY); dbg_printf("[vp8e - %08lx] vpx_codec_encode codec exit\n", (UInt32)glob); } else //sourceFrame is Null. this could be termination of a pass { int flags = 0 ; //TODO - find out what I may need in these flags dbg_printf("[vp8e - %08lx] vpx_codec_encode codec %x raw %x framecount %d ----NULL TERMINATION\n", (UInt32)glob, glob->codec, NULL, glob->frameCount, flags); codecError = vpx_codec_encode(glob->codec, NULL, time2, 1, flags, VPX_DL_GOOD_QUALITY); } glob->frameCount++ ; //framecount gets reset on a new pass if (codecError) { const char *detail = vpx_codec_error_detail(glob->codec); dbg_printf("[vp8e - %08lx] error vpx encode is %s\n", (UInt32)glob, vpx_codec_error(glob->codec)); if (detail) dbg_printf(" %s\n", detail); goto bail; } vpx_codec_iter_t iter = NULL; int got_data = 0; while (1) { const vpx_codec_cx_pkt_t *pkt = vpx_codec_get_cx_data(glob->codec, &iter); if (pkt == NULL) break; got_data ++; switch (pkt->kind) { case VPX_CODEC_CX_FRAME_PKT: err = emitEncodedFrame(glob, pkt); if (err) goto bail; break; case VPX_CODEC_STATS_PKT: if (1) { unsigned long newSize = glob->stats.sz + pkt->data.twopass_stats.sz; glob->stats.buf = realloc(glob->stats.buf, newSize); if (!glob->stats.buf) return mFulErr; dbg_printf("[vp8e - %08lx] Reallocation buffer size to %ld\n", (UInt32)glob, newSize); memcpy((char*)glob->stats.buf + glob->stats.sz, pkt->data.twopass_stats.buf, pkt->data.twopass_stats.sz); glob->stats.sz = newSize; } break; default: break; } } if (glob->currentPass == VPX_RC_FIRST_PASS) { //in the first pass no need to export any frames return err; } bail: if (err) dbg_printf("[vp8e - %08lx] bailed with err %d\n", (UInt32)glob, err); return err; }