Esempio n. 1
0
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);
}
Esempio n. 2
0
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);
}
Esempio n. 4
0
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);                                                       //
}                                                                             //
Esempio n. 6
0
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;
}
Esempio n. 7
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;
}
Esempio n. 8
0
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 ("");
}
Esempio n. 9
0
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);
}
Esempio n. 10
0
// 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;
}
Esempio n. 11
0
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);
    }
}
Esempio n. 12
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;
}
Esempio n. 13
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;

      }
Esempio n. 14
0
// 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);
}
Esempio n. 17
0
      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;

      }
Esempio n. 18
0
/****************************************************************************
 * 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;
}
Esempio n. 19
0
/*****************************************************************************
 * 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);
}
Esempio n. 20
0
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;
}
Esempio n. 21
0
File: vpx.c Progetto: 0xheart0/vlc
    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;
}
Esempio n. 23
0
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;
}