static void dec_preprocess(MSFilter* f) { DecState *s = (DecState *)f->data; vpx_codec_caps_t caps = vpx_codec_get_caps(s->iface); /* Initialize codec */ if (!s->ready){ s->flags = 0; #if 0 /* Deactivate fragments input for the vpx decoder because it has been broken in libvpx 1.4. * This will have the effect to output complete frames. */ if ((s->avpf_enabled == TRUE) && (caps & VPX_CODEC_CAP_INPUT_FRAGMENTS)) { s->flags |= VPX_CODEC_USE_INPUT_FRAGMENTS; } #endif if (caps & VPX_CODEC_CAP_ERROR_CONCEALMENT) { s->flags |= VPX_CODEC_USE_ERROR_CONCEALMENT; } if (dec_initialize_impl(f) != 0) return; ms_message("VP8: initializing decoder context: avpf=[%i] freeze_on_error=[%i]",s->avpf_enabled,s->freeze_on_error); vp8rtpfmt_unpacker_init(&s->unpacker, f, s->avpf_enabled, s->freeze_on_error, (s->flags & VPX_CODEC_USE_INPUT_FRAGMENTS) ? TRUE : FALSE); s->first_image_decoded = FALSE; s->ready=TRUE; } }
static void dec_preprocess(MSFilter* f) { DecState *s = (DecState *)f->data; vpx_codec_caps_t caps = vpx_codec_get_caps(s->iface); /* Initialize codec */ if (!s->ready){ s->flags = 0; if ((s->avpf_enabled == TRUE) && (caps & VPX_CODEC_CAP_INPUT_FRAGMENTS)) { s->flags |= VPX_CODEC_USE_INPUT_FRAGMENTS; } if (caps & VPX_CODEC_CAP_ERROR_CONCEALMENT) { s->flags |= VPX_CODEC_USE_ERROR_CONCEALMENT; } #ifdef VPX_CODEC_CAP_FRAME_THREADING if ((caps & VPX_CODEC_CAP_FRAME_THREADING) && (ms_factory_get_cpu_count(f->factory) > 1)) { s->flags |= VPX_CODEC_USE_FRAME_THREADING; } #endif if(vpx_codec_dec_init(&s->codec, s->iface, NULL, s->flags)) ms_error("Failed to initialize decoder"); ms_message("VP8: initializing decoder context: avpf=[%i] freeze_on_error=[%i]",s->avpf_enabled,s->freeze_on_error); vp8rtpfmt_unpacker_init(&s->unpacker, f, s->avpf_enabled, s->freeze_on_error, (s->flags & VPX_CODEC_USE_INPUT_FRAGMENTS) ? TRUE : FALSE); s->first_image_decoded = FALSE; s->ready=TRUE; } }
static void enc_preprocess(MSFilter *f) { EncState *s = (EncState *)f->data; vpx_codec_err_t res; vpx_codec_caps_t caps; int cpuused=0; /* Populate encoder configuration */ s->flags = 0; caps = vpx_codec_get_caps(s->iface); if ((s->avpf_enabled == TRUE) && (caps & VPX_CODEC_CAP_OUTPUT_PARTITION)) { s->flags |= VPX_CODEC_USE_OUTPUT_PARTITION; } res = vpx_codec_enc_config_default(s->iface, &s->cfg, 0); if (res) { ms_error("Failed to get config: %s", vpx_codec_err_to_string(res)); return; } s->cfg.rc_target_bitrate = (unsigned int)(((float)s->vconf.required_bitrate) * 0.92f / 1024.0f); //0.92=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 = (int)s->vconf.fps; s->cfg.rc_end_usage = VPX_CBR; /* --end-usage=cbr */ if (s->avpf_enabled == TRUE) { s->cfg.kf_mode = VPX_KF_DISABLED; } else { s->cfg.kf_mode = VPX_KF_AUTO; /* encoder automatically places keyframes */ s->cfg.kf_max_dist = 10 * s->cfg.g_timebase.den; /* 1 keyframe each 10s. */ } #if TARGET_IPHONE_SIMULATOR s->cfg.g_threads = 1; /*workaround to remove crash on ipad simulator*/ #else s->cfg.g_threads = ms_factory_get_cpu_count(f->factory); #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 = VPX_ERROR_RESILIENT_DEFAULT|VPX_ERROR_RESILIENT_PARTITIONS; s->cfg.g_lag_in_frames = 0; #if defined(ANDROID) || (TARGET_OS_IPHONE == 1) || defined(__arm__) || defined(_M_ARM) cpuused = 10 - s->cfg.g_threads; /*cpu/quality tradeoff: positive values decrease CPU usage at the expense of quality*/ if (cpuused < 7) cpuused = 7; /*values beneath 7 consume too much CPU*/ if( s->cfg.g_threads == 1 ){ /* on mono-core iOS devices, we reduce the quality a bit more due to VP8 being slower with new Clang compilers */ cpuused = 16; } #endif s->cfg.g_w = s->vconf.vsize.width; s->cfg.g_h = s->vconf.vsize.height; /* Initialize codec */ res = vpx_codec_enc_init(&s->codec, s->iface, &s->cfg, s->flags); if (res) { ms_error("vpx_codec_enc_init failed: %s (%s)", vpx_codec_err_to_string(res), vpx_codec_error_detail(&s->codec)); return; } vpx_codec_control(&s->codec, VP8E_SET_CPUUSED, cpuused); vpx_codec_control(&s->codec, VP8E_SET_STATIC_THRESHOLD, 0); vpx_codec_control(&s->codec, VP8E_SET_ENABLEAUTOALTREF, !s->avpf_enabled); vpx_codec_control(&s->codec, VP8E_SET_MAX_INTRA_BITRATE_PCT, 400); /*limite iFrame size to 4 pframe*/ if (s->flags & VPX_CODEC_USE_OUTPUT_PARTITION) { vpx_codec_control(&s->codec, VP8E_SET_TOKEN_PARTITIONS, 2); /* Output 4 partitions per frame */ } else { vpx_codec_control(&s->codec, VP8E_SET_TOKEN_PARTITIONS, 0); } s->invalid_frame_reported = FALSE; vp8rtpfmt_packer_init(&s->packer); if (s->avpf_enabled == TRUE) { s->force_keyframe = TRUE; } else if (s->frame_count == 0) { ms_video_starter_init(&s->starter); } s->ready = TRUE; }
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; }
static GstFlowReturn open_codec (GstVP9Dec * dec, GstVideoCodecFrame * frame) { int flags = 0; vpx_codec_stream_info_t stream_info; vpx_codec_caps_t caps; vpx_codec_dec_cfg_t cfg; vpx_codec_err_t status; GstMapInfo minfo; memset (&stream_info, 0, sizeof (stream_info)); memset (&cfg, 0, sizeof (cfg)); stream_info.sz = sizeof (stream_info); if (!gst_buffer_map (frame->input_buffer, &minfo, GST_MAP_READ)) { GST_ERROR_OBJECT (dec, "Failed to map input buffer"); return GST_FLOW_ERROR; } status = vpx_codec_peek_stream_info (&vpx_codec_vp9_dx_algo, minfo.data, minfo.size, &stream_info); gst_buffer_unmap (frame->input_buffer, &minfo); if (status != VPX_CODEC_OK) { GST_WARNING_OBJECT (dec, "VPX preprocessing error: %s", gst_vpx_error_name (status)); gst_video_decoder_drop_frame (GST_VIDEO_DECODER (dec), frame); return GST_FLOW_CUSTOM_SUCCESS_1; } if (!stream_info.is_kf) { GST_WARNING_OBJECT (dec, "No keyframe, skipping"); gst_video_decoder_drop_frame (GST_VIDEO_DECODER (dec), frame); return GST_FLOW_CUSTOM_SUCCESS_1; } /* FIXME: peek_stream_info() does not return valid values, take input caps */ stream_info.w = dec->input_state->info.width; stream_info.h = dec->input_state->info.height; cfg.w = stream_info.w; cfg.h = stream_info.h; cfg.threads = dec->threads; caps = vpx_codec_get_caps (&vpx_codec_vp9_dx_algo); if (dec->post_processing) { if (!(caps & VPX_CODEC_CAP_POSTPROC)) { GST_WARNING_OBJECT (dec, "Decoder does not support post processing"); } else { flags |= VPX_CODEC_USE_POSTPROC; } } status = vpx_codec_dec_init (&dec->decoder, &vpx_codec_vp9_dx_algo, &cfg, flags); if (status != VPX_CODEC_OK) { GST_ELEMENT_ERROR (dec, LIBRARY, INIT, ("Failed to initialize VP9 decoder"), ("%s", gst_vpx_error_name (status))); return GST_FLOW_ERROR; } if ((caps & VPX_CODEC_CAP_POSTPROC) && dec->post_processing) { vp8_postproc_cfg_t pp_cfg = { 0, }; pp_cfg.post_proc_flag = dec->post_processing_flags; pp_cfg.deblocking_level = dec->deblocking_level; pp_cfg.noise_level = dec->noise_level; status = vpx_codec_control (&dec->decoder, VP8_SET_POSTPROC, &pp_cfg); if (status != VPX_CODEC_OK) { GST_WARNING_OBJECT (dec, "Couldn't set postprocessing settings: %s", gst_vpx_error_name (status)); } } dec->decoder_inited = TRUE; return GST_FLOW_OK; }