Esempio n. 1
0
bool readImage(char *filename, int frameNumber, vpx_image_t **pRGBImage, vpx_image_t **pYV12Image, int flip)
{
	// Load image.
	//
	char path[512];
	sprintf(path, filename, frameNumber);

	ILuint imageHandle;
	ilGenImages(1, &imageHandle);
	ilBindImage(imageHandle);

	ILboolean ok = ilLoadImage(path);

	if (ok)
	{
		if (ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE))
		{
			unsigned int w = ilGetInteger(IL_IMAGE_WIDTH);
			unsigned int h = ilGetInteger(IL_IMAGE_HEIGHT);

			if (*pRGBImage == NULL)
			{
				*pRGBImage = vpx_img_alloc(NULL, VPX_IMG_FMT_RGB24, w, h, 1);
			}

			if (*pYV12Image == NULL)
			{
				*pYV12Image = vpx_img_alloc(NULL, VPX_IMG_FMT_I420, w, h, 1);
			}

			memcpy((*pRGBImage)->img_data, ilGetData(), w * h * 3);

			rgb24toyv12(*pRGBImage, *pYV12Image);

			if (flip)
			{
				vpx_img_flip(*pYV12Image);
			}

			ilDeleteImages(1, &imageHandle);

			return true;
		}
	}
	else
	{
		ILenum ilError = ilGetError();
		fprintf(stderr, "Can't load [%s], [%x %s]\n.", path, ilError, iluErrorString(ilError));
	}

	return false;
}
Esempio n. 2
0
krad_vpx_encoder_t *krad_vpx_encoder_create (int width, int height, int fps_numerator,
											 int fps_denominator, int bitrate) {

	krad_vpx_encoder_t *kradvpx;
	
	kradvpx = calloc(1, sizeof(krad_vpx_encoder_t));
	
	kradvpx->width = width;
	kradvpx->height = height;
	kradvpx->fps_numerator = fps_numerator;
	kradvpx->fps_denominator = fps_denominator;
	kradvpx->bitrate = bitrate;
	
	printk ("Krad Radio using libvpx version: %s", vpx_codec_version_str ());

	if ((kradvpx->image = vpx_img_alloc (NULL, VPX_IMG_FMT_YV12, kradvpx->width, kradvpx->height, 1)) == NULL) {
		failfast ("Failed to allocate vpx image\n");
	}

	kradvpx->res = vpx_codec_enc_config_default (vpx_codec_vp8_cx(), &kradvpx->cfg, 0);

	if (kradvpx->res) {
		failfast ("Failed to get config: %s\n", vpx_codec_err_to_string(kradvpx->res));
    }

	// print default config
	//krad_vpx_encoder_print_config (kradvpx);

	kradvpx->cfg.g_w = kradvpx->width;
	kradvpx->cfg.g_h = kradvpx->height;
	/* Next two lines are really right */
	kradvpx->cfg.g_timebase.num = kradvpx->fps_denominator;
	kradvpx->cfg.g_timebase.den = kradvpx->fps_numerator;
	kradvpx->cfg.rc_target_bitrate = bitrate;	
	kradvpx->cfg.g_threads = 4;
	kradvpx->cfg.kf_mode = VPX_KF_AUTO;
	kradvpx->cfg.rc_end_usage = VPX_VBR;
	
	kradvpx->deadline = 15 * 1000;

	kradvpx->min_quantizer = kradvpx->cfg.rc_min_quantizer;
	kradvpx->max_quantizer = kradvpx->cfg.rc_max_quantizer;

	//krad_vpx_encoder_print_config (kradvpx);

	if (vpx_codec_enc_init(&kradvpx->encoder, vpx_codec_vp8_cx(), &kradvpx->cfg, 0)) {
		 krad_vpx_fail (&kradvpx->encoder, "Failed to initialize encoder");
	}

	//krad_vpx_encoder_print_config (kradvpx);


#ifdef BENCHMARK
	printk ("Benchmarking enabled, reporting every %d frames", BENCHMARK_COUNT);
kradvpx->krad_timer = krad_timer_create();
#endif

	return kradvpx;

}
Esempio n. 3
0
static bool video_device_init(void *handle) {
    // initialize video (will populate video_width and video_height)
    if (handle == (void *)1) {
        if (!native_video_init((void *)1)) {
            LOG_TRACE("uToxVideo", "native_video_init() failed for desktop" );
            return false;
        }
    } else {
        if (!handle || !native_video_init(*(void **)handle)) {
            LOG_TRACE("uToxVideo", "native_video_init() failed webcam" );
            return false;
        }
    }
    vpx_img_alloc(&input, VPX_IMG_FMT_I420, video_width, video_height, 1);
    utox_video_frame.y = input.planes[0];
    utox_video_frame.u = input.planes[1];
    utox_video_frame.v = input.planes[2];
    utox_video_frame.w = input.d_w;
    utox_video_frame.h = input.d_h;

    LOG_NOTE("uToxVideo", "video init done!" );
    video_device_status = true;

    return true;
}
Esempio n. 4
0
 VpxImage& operator =(const VpxImage& src) {
   if (image_) {
     vpx_img_free(image_);
     image_ = 0;
   }
   assert(src.format() == VPX_IMG_FMT_RGB24);
   image_ = vpx_img_alloc(NULL, src.format(), src.width(), src.height(), 1);
   if (image_) {
     memcpy(image_->img_data, src.buffer(), width()*height()*3);
   }
   return *this;
 }
Esempio n. 5
0
int vp8Encoder::initilize(int frameWidth, int frameHeight)
{
    //display_width = frameWidth;
    //display_height = frameHeight;

    pthread_mutex_lock (&mCodecLock);
    frame_cnt = 0;

    vpx_codec_enc_cfg_t    cfg;
    int cpu_used = 8;
    int static_threshold = 1200;

    vpx_codec_enc_config_default(interface, &cfg, 0);
    LOGD("Using %s\n",vpx_codec_iface_name(interface));

    cfg.rc_target_bitrate = 10*frameWidth * frameHeight * cfg.rc_target_bitrate
        / cfg.g_w / cfg.g_h;
    LOGD("Encoder cfg.rc_target_bitrate=%d", cfg.rc_target_bitrate);
    cfg.g_w = display_width;
    cfg.g_h = display_height;
    /*cfg.g_timebase.num = 1;
    cfg.g_timebase.den = (int) 10000000;
    cfg.rc_end_usage = VPX_CBR;
    cfg.g_pass = VPX_RC_ONE_PASS;
    cfg.g_lag_in_frames = 0;
    cfg.rc_min_quantizer = 20;
    cfg.rc_max_quantizer = 50;
    cfg.rc_dropframe_thresh = 1;
    cfg.rc_buf_optimal_sz = 1000;
    cfg.rc_buf_initial_sz = 1000;
    cfg.rc_buf_sz = 1000;
    cfg.g_error_resilient = 1;
    cfg.kf_mode = VPX_KF_DISABLED;
    cfg.kf_max_dist = 999999;
    cfg.g_threads = 1;*/

    vpx_codec_enc_init(&encoder, interface, &cfg, 0);
    /*vpx_codec_control_(&encoder, VP8E_SET_CPUUSED, cpu_used);
    vpx_codec_control_(&encoder, VP8E_SET_STATIC_THRESHOLD, static_threshold);
    vpx_codec_control_(&encoder, VP8E_SET_ENABLEAUTOALTREF, 0);
    */
    vpx_img_alloc(&raw, VPX_IMG_FMT_I420, display_width, display_height, 1);

    //create_packetizer(&x, XOR, fec_numerator, fec_denominator);

    //sDecoder->initilize();
    pthread_mutex_unlock (&mCodecLock);
    return 0;
}
Esempio n. 6
0
void WebMEncoder::initializeVideoEncoder() {
    /* Populate encoder configuration */
    vpx_codec_err_t res = vpx_codec_enc_config_default(&vpx_enc_vp8_algo, &cfg, 0);
    
    if (res) {
        fprintf(stderr, "Failed to get config: %s\n",
                vpx_codec_err_to_string(res));
	    exit(1);
    }

    if(boost::thread::hardware_concurrency()) {
        cfg.g_threads = boost::thread::hardware_concurrency() - 1;
    }

    /* Change the default timebase to a high enough value so that the encoder
     * will always create strictly increasing timestamps.
     */
    cfg.g_timebase.num = 1;
    cfg.g_timebase.den = 30;

    // lag_in_frames allows for extra optimization at the expense of not writing frames in realtime
    cfg.g_lag_in_frames = 5;

    // Variable bit rate
    cfg.rc_end_usage = VPX_VBR;

    // Target data rate in Kbps (lowercase b)
    cfg.rc_target_bitrate = 1024; //1 Mbit/sec
    
    /* Never use the library's default resolution, require it be parsed
     * from the file or set on the command line.
     */
    cfg.g_w = width;
    cfg.g_h = height;
    
    vpx_img_alloc(&raw, VPX_IMG_FMT_YV12,
                  cfg.g_w, cfg.g_h, 1);
    
    cfg.g_pass = VPX_RC_ONE_PASS;
    
    /* Construct Encoder Context */
    vpx_codec_enc_init(&encoder, &vpx_enc_vp8_algo, &cfg, 0);
    if(encoder.err) {
        printf("Failed to initialize encoder\n");
    }
}
    information()
    {
        m_raw.planes[0] = NULL;
        m_codec.iface = NULL;

        vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &m_cfg, 0);

        m_cfg.rc_target_bitrate = 2000;
        m_cfg.g_w = 640;
        m_cfg.g_h = 480;

        m_frameCnt = 0;

        vpx_codec_enc_init(&m_codec, vpx_codec_vp8_cx(), &m_cfg, 0);

        vpx_img_alloc(&m_raw, VPX_IMG_FMT_I420, 640, 480, 1);
    }
Esempio n. 8
0
static
void dispatchFrameCb(int32_t width, int32_t height, const uint8_t* buffer, int32_t length, void* ctxt)
{
    struct CamTox* tox = (struct CamTox*)ctxt;
    static uint8_t* frame = NULL;
    if (!frame) {
        frame = calloc(1, width * height * 3);
        if (!frame) return;
    }

    static vpx_image_t input;
    static int alloced = 0;
    static uint8_t* y = NULL;
    static uint8_t* u = NULL;
    static uint8_t* v = NULL;
    static uint16_t w = 0;
    static uint16_t h = 0;

    if (!alloced) {
        vpx_img_alloc(&input, VPX_IMG_FMT_I420, width, height, 1);
        y = input.planes[0];
        u = input.planes[1];
        v = input.planes[2];
        w = input.d_w;
        h = input.d_h;
        alloced = 1;
    }

    if ((w != width) || (h != height)) {
        printf(" width, height mismatch.\n");
        return;
    }

    uint8_t* dst = frame + width * height * 3;
    uint8_t* src = (uint8_t*) buffer;
    int32_t  sz  = width * 3;
    for (int i = 0; i < height; i++) {
        dst -= sz;
        memcpy(dst, src, sz);
        src += sz;
    }
    bgrtoyuv420(y, u, v, frame, width, height);
    tox->ops->sendVideoFrame(tox, y, u, v, w, h);

    return;
}
Esempio n. 9
0
JNIEXPORT jint Java_ryulib_VideoZip_VPX_OpenEncoder(JNIEnv* env,
		jclass clazz, jint width, jint height, jint bitRate, int fps, int gop)
{
	RyuVPX *pHandle = (RyuVPX *) malloc(sizeof(RyuVPX));
	
	pHandle->errorCode = 0;

	if (!vpx_img_alloc(&pHandle->img, VPX_IMG_FMT_I420 , width, height, 1)) {
		pHandle->errorCode = _Error_Allocate_Image;
		goto EXIT;
	}

	if (vpx_codec_enc_config_default(interfaceEnc, &pHandle->cfgEnc, 0)) {
		pHandle->errorCode = _Error_Getting_Config;
		goto EXIT;
	}

	pHandle->cfgEnc.g_w = width;
	pHandle->cfgEnc.g_h = height;
	pHandle->cfgEnc.rc_target_bitrate = bitRate;

	if (0 != bitRate) {
		pHandle->cfgEnc.rc_target_bitrate = bitRate;
	} else {
		pHandle->cfgEnc.rc_target_bitrate = width * height * pHandle->cfgEnc.rc_target_bitrate  / pHandle->cfgEnc.g_w / pHandle->cfgEnc.g_h;    
	}

	if (0 != gop) {
		pHandle->cfgEnc.kf_max_dist = gop;
	} 

	if (-1 == gop) {
		pHandle->cfgEnc.kf_mode = VPX_KF_DISABLED;
	}

	if (vpx_codec_enc_init(&pHandle->codec, interfaceEnc, &pHandle->cfgEnc, 0)) {
		pHandle->errorCode = _Error_Init_VideoCodec;
		goto EXIT;
	}

EXIT:

	return pHandle;
}
Esempio n. 10
0
HRESULT InitVPXEncoder(vpx_codec_enc_cfg_t * vpxConfig, vpx_codec_ctx_t * vpxCodec, unsigned int width, unsigned int height)
{
	//vpx_codec_ctx_t      codec;

	vpx_codec_err_t res;

	printf("Using %s\n", vpx_codec_iface_name(vpx_codec_vp8_cx()));

	/* Populate encoder configuration */
	res = vpx_codec_enc_config_default((vpx_codec_vp8_cx()), vpxConfig, 0);

	if (res) {
		printf("Failed to get VPX codec config: %s\n", vpx_codec_err_to_string(res));
		return -1;
	}
	else {
		vpx_img_alloc(&_rawImage, VIDEO_INPUT_FORMAT, WIDTH, HEIGHT, 0);

		vpxConfig->g_w = width;
		vpxConfig->g_h = height;
		vpxConfig->rc_target_bitrate = 5000; // in kbps.
		vpxConfig->rc_min_quantizer = 20; // 50;
		vpxConfig->rc_max_quantizer = 30; // 60;
		vpxConfig->g_pass = VPX_RC_ONE_PASS;
		vpxConfig->rc_end_usage = VPX_CBR;
		//vpxConfig->kf_min_dist = 50;
		//vpxConfig->kf_max_dist = 50;
		//vpxConfig->kf_mode = VPX_KF_DISABLED;
		vpxConfig->g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT;
		vpxConfig->g_lag_in_frames = 0;
		vpxConfig->rc_resize_allowed = 0;

		/* Initialize codec */
		if (vpx_codec_enc_init(vpxCodec, (vpx_codec_vp8_cx()), vpxConfig, 0)) {
			printf("Failed to initialize libvpx encoder.\n");
			return -1;
		}
		else {
			return S_OK;
		}
	}
}
Esempio n. 11
0
	int VPXEncoder::InitEncoder(unsigned int width, unsigned int height)
	{
		_vpxCodec = new vpx_codec_ctx_t();
		_rawImage = new vpx_image_t();
		_width = width;
		_height = height;

		vpx_codec_enc_cfg_t vpxConfig;
		vpx_codec_err_t res;

		printf("Using %s\n", vpx_codec_iface_name(vpx_codec_vp8_cx()));

		/* Populate encoder configuration */
		res = vpx_codec_enc_config_default((vpx_codec_vp8_cx()), &vpxConfig, 0);

		if (res) {
			printf("Failed to get VPX codec config: %s\n", vpx_codec_err_to_string(res));
			return -1;
		}
		else {
			vpx_img_alloc(_rawImage, VPX_IMG_FMT_I420, width, height, 0);

			vpxConfig.g_w = width;
			vpxConfig.g_h = height;
			vpxConfig.rc_target_bitrate = 300; // 5000; // in kbps.
			vpxConfig.rc_min_quantizer = 20; // 50;
			vpxConfig.rc_max_quantizer = 30; // 60;
			vpxConfig.g_pass = VPX_RC_ONE_PASS;
			vpxConfig.rc_end_usage = VPX_CBR;
			vpxConfig.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT;
			vpxConfig.g_lag_in_frames = 0;
			vpxConfig.rc_resize_allowed = 0;
			vpxConfig.kf_max_dist = 20;

			/* Initialize codec */
			if (vpx_codec_enc_init(_vpxCodec, (vpx_codec_vp8_cx()), &vpxConfig, 0)) {
				printf("Failed to initialize libvpx encoder.\n");
				return -1;
			}
		}
	}
Esempio n. 12
0
int start_encode(encoding_context *context, char *path, int width, int height, float fps, int *durations, int deadline) {
	if (0!=vpx_codec_enc_config_default(WG_CODEC_INTERFACE, &context->cfg, 0)) return 1000;
	context->cfg.g_w = width;
	context->cfg.g_h = height;
	context->deadline = deadline; // microseconds to spend encoding each frame
	context->timebase_units_per_second = 30.0f; // always 30?
	context->frames_per_second = fps;
	context->frame_durations = durations;
	
	FILE *outfile = fopen(path, "wb");
	if (!outfile) return 1001;
	context->ebml.stream = outfile;
	
	if (!vpx_img_alloc(&context->vpx_image, VPX_IMG_FMT_I420, width, height, 1)) return 1002;
	
	if (0!=vpx_codec_enc_init(&context->codec, WG_CODEC_INTERFACE, &context->cfg, 0)) return 1003;
	
	struct vpx_rational framerate = {fps, 1};
	const struct VpxRational pixel_aspect_ratio = {1, 1};
	write_webm_file_header(&context->ebml, &context->cfg, &framerate, STEREO_FORMAT_MONO, WG_FOURCC, &pixel_aspect_ratio);
	
	return 0;
}
Esempio n. 13
0
int main(int argc, char **argv) {
  VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = {NULL};
  vpx_codec_ctx_t codec;
  vpx_codec_enc_cfg_t cfg;
  int frame_cnt = 0;
  vpx_image_t raw;
  vpx_codec_err_t res;
  unsigned int width;
  unsigned int height;
  int speed;
  int frame_avail;
  int got_data;
  int flags = 0;
  unsigned int i;
  int pts = 0;  // PTS starts at 0.
  int frame_duration = 1;  // 1 timebase tick per frame.
  int layering_mode = 0;
  int layer_flags[VPX_TS_MAX_PERIODICITY] = {0};
  int flag_periodicity = 1;
  vpx_svc_layer_id_t layer_id = {0, 0};
  const VpxInterface *encoder = NULL;
  FILE *infile = NULL;
  struct RateControlMetrics rc;
  int64_t cx_time = 0;
  const int min_args_base = 11;
#if CONFIG_VP9_HIGHBITDEPTH
  vpx_bit_depth_t bit_depth = VPX_BITS_8;
  int input_bit_depth = 8;
  const int min_args = min_args_base + 1;
#else
  const int min_args = min_args_base;
#endif  // CONFIG_VP9_HIGHBITDEPTH
  double sum_bitrate = 0.0;
  double sum_bitrate2 = 0.0;
  double framerate  = 30.0;

  exec_name = argv[0];
  // Check usage and arguments.
  if (argc < min_args) {
#if CONFIG_VP9_HIGHBITDEPTH
    die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> "
        "<rate_num> <rate_den> <speed> <frame_drop_threshold> <mode> "
        "<Rate_0> ... <Rate_nlayers-1> <bit-depth> \n", argv[0]);
#else
    die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> "
        "<rate_num> <rate_den> <speed> <frame_drop_threshold> <mode> "
        "<Rate_0> ... <Rate_nlayers-1> \n", argv[0]);
#endif  // CONFIG_VP9_HIGHBITDEPTH
  }

  encoder = get_vpx_encoder_by_name(argv[3]);
  if (!encoder)
    die("Unsupported codec.");

  printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));

  width = strtol(argv[4], NULL, 0);
  height = strtol(argv[5], NULL, 0);
  if (width < 16 || width % 2 || height < 16 || height % 2) {
    die("Invalid resolution: %d x %d", width, height);
  }

  layering_mode = strtol(argv[10], NULL, 0);
  if (layering_mode < 0 || layering_mode > 12) {
    die("Invalid layering mode (0..12) %s", argv[10]);
  }

  if (argc != min_args + mode_to_num_layers[layering_mode]) {
    die("Invalid number of arguments");
  }

#if CONFIG_VP9_HIGHBITDEPTH
  switch (strtol(argv[argc-1], NULL, 0)) {
    case 8:
      bit_depth = VPX_BITS_8;
      input_bit_depth = 8;
      break;
    case 10:
      bit_depth = VPX_BITS_10;
      input_bit_depth = 10;
      break;
    case 12:
      bit_depth = VPX_BITS_12;
      input_bit_depth = 12;
      break;
    default:
      die("Invalid bit depth (8, 10, 12) %s", argv[argc-1]);
  }
  if (!vpx_img_alloc(&raw,
                     bit_depth == VPX_BITS_8 ? VPX_IMG_FMT_I420 :
                                               VPX_IMG_FMT_I42016,
                     width, height, 32)) {
    die("Failed to allocate image", width, height);
  }
#else
  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 32)) {
    die("Failed to allocate image", width, height);
  }
#endif  // CONFIG_VP9_HIGHBITDEPTH

  // Populate encoder configuration.
  res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
  if (res) {
    printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
    return EXIT_FAILURE;
  }

  // Update the default configuration with our settings.
  cfg.g_w = width;
  cfg.g_h = height;

#if CONFIG_VP9_HIGHBITDEPTH
  if (bit_depth != VPX_BITS_8) {
    cfg.g_bit_depth = bit_depth;
    cfg.g_input_bit_depth = input_bit_depth;
    cfg.g_profile = 2;
  }
#endif  // CONFIG_VP9_HIGHBITDEPTH

  // Timebase format e.g. 30fps: numerator=1, demoninator = 30.
  cfg.g_timebase.num = strtol(argv[6], NULL, 0);
  cfg.g_timebase.den = strtol(argv[7], NULL, 0);

  speed = strtol(argv[8], NULL, 0);
  if (speed < 0) {
    die("Invalid speed setting: must be positive");
  }

  for (i = min_args_base;
       (int)i < min_args_base + mode_to_num_layers[layering_mode];
       ++i) {
    cfg.ts_target_bitrate[i - 11] = strtol(argv[i], NULL, 0);
  }

  // Real time parameters.
  cfg.rc_dropframe_thresh = strtol(argv[9], NULL, 0);
  cfg.rc_end_usage = VPX_CBR;
  cfg.rc_resize_allowed = 0;
  cfg.rc_min_quantizer = 2;
  cfg.rc_max_quantizer = 56;
  cfg.rc_undershoot_pct = 50;
  cfg.rc_overshoot_pct = 50;
  cfg.rc_buf_initial_sz = 500;
  cfg.rc_buf_optimal_sz = 600;
  cfg.rc_buf_sz = 1000;

  // Enable error resilient mode.
  cfg.g_error_resilient = 1;
  cfg.g_lag_in_frames   = 0;
  cfg.kf_mode = VPX_KF_AUTO;

  // Disable automatic keyframe placement.
  cfg.kf_min_dist = cfg.kf_max_dist = 3000;

  set_temporal_layer_pattern(layering_mode,
                             &cfg,
                             layer_flags,
                             &flag_periodicity);

  set_rate_control_metrics(&rc, &cfg);

  // Target bandwidth for the whole stream.
  // Set to ts_target_bitrate for highest layer (total bitrate).
  cfg.rc_target_bitrate = cfg.ts_target_bitrate[cfg.ts_number_layers - 1];

  // Open input file.
  if (!(infile = fopen(argv[1], "rb"))) {
    die("Failed to open %s for reading", argv[1]);
  }

  framerate = cfg.g_timebase.den / cfg.g_timebase.num;
  // Open an output file for each stream.
  for (i = 0; i < cfg.ts_number_layers; ++i) {
    char file_name[PATH_MAX];
    VpxVideoInfo info;
    info.codec_fourcc = encoder->fourcc;
    info.frame_width = cfg.g_w;
    info.frame_height = cfg.g_h;
    info.time_base.numerator = cfg.g_timebase.num;
    info.time_base.denominator = cfg.g_timebase.den;

    snprintf(file_name, sizeof(file_name), "%s_%d.ivf", argv[2], i);
    outfile[i] = vpx_video_writer_open(file_name, kContainerIVF, &info);
    if (!outfile[i])
      die("Failed to open %s for writing", file_name);

    assert(outfile[i] != NULL);
  }
  // No spatial layers in this encoder.
  cfg.ss_number_layers = 1;

  // Initialize codec.
#if CONFIG_VP9_HIGHBITDEPTH
  if (vpx_codec_enc_init(
          &codec, encoder->codec_interface(), &cfg,
          bit_depth == VPX_BITS_8 ? 0 : VPX_CODEC_USE_HIGHBITDEPTH))
#else
  if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
#endif  // CONFIG_VP9_HIGHBITDEPTH
    die_codec(&codec, "Failed to initialize encoder");

  if (strncmp(encoder->name, "vp8", 3) == 0) {
    vpx_codec_control(&codec, VP8E_SET_CPUUSED, -speed);
    vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, kDenoiserOnYOnly);
  } else if (strncmp(encoder->name, "vp9", 3) == 0) {
      vpx_codec_control(&codec, VP8E_SET_CPUUSED, speed);
      vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3);
      vpx_codec_control(&codec, VP9E_SET_FRAME_PERIODIC_BOOST, 0);
      vpx_codec_control(&codec, VP9E_SET_NOISE_SENSITIVITY, 0);
      if (vpx_codec_control(&codec, VP9E_SET_SVC, layering_mode > 0 ? 1: 0)) {
        die_codec(&codec, "Failed to set SVC");
    }
  }
  vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1);
  vpx_codec_control(&codec, VP8E_SET_TOKEN_PARTITIONS, 1);
  // This controls the maximum target size of the key frame.
  // For generating smaller key frames, use a smaller max_intra_size_pct
  // value, like 100 or 200.
  {
    const int max_intra_size_pct = 900;
    vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT,
                      max_intra_size_pct);
  }

  frame_avail = 1;
  while (frame_avail || got_data) {
    struct vpx_usec_timer timer;
    vpx_codec_iter_t iter = NULL;
    const vpx_codec_cx_pkt_t *pkt;
    // Update the temporal layer_id. No spatial layers in this test.
    layer_id.spatial_layer_id = 0;
    layer_id.temporal_layer_id =
        cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
    if (strncmp(encoder->name, "vp9", 3) == 0) {
      vpx_codec_control(&codec, VP9E_SET_SVC_LAYER_ID, &layer_id);
    }
    flags = layer_flags[frame_cnt % flag_periodicity];
    frame_avail = vpx_img_read(&raw, infile);
    if (frame_avail)
      ++rc.layer_input_frames[layer_id.temporal_layer_id];
    vpx_usec_timer_start(&timer);
    if (vpx_codec_encode(&codec, frame_avail? &raw : NULL, pts, 1, flags,
        VPX_DL_REALTIME)) {
      die_codec(&codec, "Failed to encode frame");
    }
    vpx_usec_timer_mark(&timer);
    cx_time += vpx_usec_timer_elapsed(&timer);
    // Reset KF flag.
    if (layering_mode != 7) {
      layer_flags[0] &= ~VPX_EFLAG_FORCE_KF;
    }
    got_data = 0;
    while ( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
      got_data = 1;
      switch (pkt->kind) {
        case VPX_CODEC_CX_FRAME_PKT:
          for (i = cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
              i < cfg.ts_number_layers; ++i) {
            vpx_video_writer_write_frame(outfile[i], pkt->data.frame.buf,
                                         pkt->data.frame.sz, pts);
            ++rc.layer_tot_enc_frames[i];
            rc.layer_encoding_bitrate[i] += 8.0 * pkt->data.frame.sz;
            // Keep count of rate control stats per layer (for non-key frames).
            if (i == cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity] &&
                !(pkt->data.frame.flags & VPX_FRAME_IS_KEY)) {
              rc.layer_avg_frame_size[i] += 8.0 * pkt->data.frame.sz;
              rc.layer_avg_rate_mismatch[i] +=
                  fabs(8.0 * pkt->data.frame.sz - rc.layer_pfb[i]) /
                  rc.layer_pfb[i];
              ++rc.layer_enc_frames[i];
            }
          }
          // Update for short-time encoding bitrate states, for moving window
          // of size rc->window, shifted by rc->window / 2.
          // Ignore first window segment, due to key frame.
          if (frame_cnt > rc.window_size) {
            sum_bitrate += 0.001 * 8.0 * pkt->data.frame.sz * framerate;
            if (frame_cnt % rc.window_size == 0) {
              rc.window_count += 1;
              rc.avg_st_encoding_bitrate += sum_bitrate / rc.window_size;
              rc.variance_st_encoding_bitrate +=
                  (sum_bitrate / rc.window_size) *
                  (sum_bitrate / rc.window_size);
              sum_bitrate = 0.0;
            }
          }
          // Second shifted window.
          if (frame_cnt > rc.window_size + rc.window_size / 2) {
            sum_bitrate2 += 0.001 * 8.0 * pkt->data.frame.sz * framerate;
            if (frame_cnt > 2 * rc.window_size &&
                frame_cnt % rc.window_size == 0) {
              rc.window_count += 1;
              rc.avg_st_encoding_bitrate += sum_bitrate2 / rc.window_size;
              rc.variance_st_encoding_bitrate +=
                  (sum_bitrate2 / rc.window_size) *
                  (sum_bitrate2 / rc.window_size);
              sum_bitrate2 = 0.0;
            }
          }
          break;
          default:
            break;
      }
    }
    ++frame_cnt;
    pts += frame_duration;
  }
  fclose(infile);
  printout_rate_control_summary(&rc, &cfg, frame_cnt);
  printf("\n");
  printf("Frame cnt and encoding time/FPS stats for encoding: %d %f %f \n",
          frame_cnt,
          1000 * (float)cx_time / (double)(frame_cnt * 1000000),
          1000000 * (double)frame_cnt / (double)cx_time);

  if (vpx_codec_destroy(&codec))
    die_codec(&codec, "Failed to destroy codec");

  // Try to rewrite the output file headers with the actual frame count.
  for (i = 0; i < cfg.ts_number_layers; ++i)
    vpx_video_writer_close(outfile[i]);

  vpx_img_free(&raw);
  return EXIT_SUCCESS;
}
Esempio n. 14
0
void VideoProgress::onNextFrame() {
  size_t maxFrames = encoder->fpsValue() * durationSeconds;

  renderSurface->renderNow(frameCount/float(encoder->fpsValue()));
  QImage image = renderSurface->getImage();

  //if (!frameCount || frameCount % 3 == 0) {
    QImage preview = image.scaled(320,200,Qt::KeepAspectRatio,Qt::FastTransformation);
    frame->setPixmap(QPixmap::fromImage(preview));
  //}

  image = image.convertToFormat(QImage::Format_RGB888);

  vpx_image_t* vpxImage = vpx_img_alloc(NULL, VPX_IMG_FMT_RGB24, renderSurface->width(), renderSurface->height(), 1);
  if (!vpxImage) {
    finishCapture("An error occured during capture: Out of memory.");
    return;
  }

  size_t size = renderSurface->width() * renderSurface->height() * 3;
  if (size != size_t(image.byteCount())) {
    finishCapture("An error occured during capture: Image size error.");
    vpx_img_free(vpxImage);
    return;
  }

  memcpy(vpxImage->img_data, image.bits(), size);

  if (!encoder->writeFrame(vpxImage)) {
    finishCapture("An error occured during capture: Frame write error.");
    vpx_img_free(vpxImage);
    return;
  }

  if (vpxImage) {
    vpx_img_free(vpxImage);
  }

  bool complete = false;
  if (++frameCount == maxFrames) {
    finalFrame = true;
    complete = true;
  } else {
    bar->setValue(frameCount/float(maxFrames)*100);
  }

  if (finalFrame) {
    bar->setValue(100);
    encoder->finish();
    delete encoder;
    if (complete) {
      finishCapture("The capture is complete.");
    } else {
      finishCapture("The capture was canceled.");
    }
  }

  if (!finalFrame) {
    QTimer::singleShot(0, this, SLOT(onNextFrame()));
  }
}
Esempio n. 15
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;
}
int main(int argc, char **argv) {
    FILE                *infile, *outfile[MAX_LAYERS];
    vpx_codec_ctx_t      codec;
    vpx_codec_enc_cfg_t  cfg;
    int                  frame_cnt = 0;
    vpx_image_t          raw;
    vpx_codec_err_t      res;
    unsigned int         width;
    unsigned int         height;
    int                  frame_avail;
    int                  got_data;
    int                  flags = 0;
    int                  i;
    int                  pts = 0;              // PTS starts at 0
    int                  frame_duration = 1;   // 1 timebase tick per frame

    int                  layering_mode = 0;
    int                  frames_in_layer[MAX_LAYERS] = {0};
    int                  layer_flags[MAX_PERIODICITY] = {0};

    // Check usage and arguments
    if (argc < 9)
        die("Usage: %s <infile> <outfile> <width> <height> <rate_num> "
            " <rate_den> <mode> <Rate_0> ... <Rate_nlayers-1>\n", argv[0]);

    width  = strtol (argv[3], NULL, 0);
    height = strtol (argv[4], NULL, 0);
    if (width < 16 || width%2 || height <16 || height%2)
        die ("Invalid resolution: %d x %d", width, height);

    if (!sscanf(argv[7], "%d", &layering_mode))
        die ("Invalid mode %s", argv[7]);
    if (layering_mode<0 || layering_mode>6)
        die ("Invalid mode (0..6) %s", argv[7]);

    if (argc != 8+mode_to_num_layers[layering_mode])
        die ("Invalid number of arguments");

    if (!vpx_img_alloc (&raw, VPX_IMG_FMT_I420, width, height, 1))
        die ("Failed to allocate image", width, height);

    printf("Using %s\n",vpx_codec_iface_name(interface));

    // Populate encoder configuration
    res = vpx_codec_enc_config_default(interface, &cfg, 0);
    if(res) {
        printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
        return EXIT_FAILURE;
    }

    // Update the default configuration with our settings
    cfg.g_w = width;
    cfg.g_h = height;

    // Timebase format e.g. 30fps: numerator=1, demoninator=30
    if (!sscanf (argv[5], "%d", &cfg.g_timebase.num ))
        die ("Invalid timebase numerator %s", argv[5]);
    if (!sscanf (argv[6], "%d", &cfg.g_timebase.den ))
        die ("Invalid timebase denominator %s", argv[6]);

    for (i=8; i<8+mode_to_num_layers[layering_mode]; i++)
        if (!sscanf(argv[i], "%d", &cfg.ts_target_bitrate[i-8]))
            die ("Invalid data rate %s", argv[i]);

    // Real time parameters
    cfg.rc_dropframe_thresh = 0;
    cfg.rc_end_usage        = VPX_CBR;
    cfg.rc_resize_allowed   = 0;
    cfg.rc_min_quantizer    = 4;
    cfg.rc_max_quantizer    = 63;
    cfg.rc_undershoot_pct   = 98;
    cfg.rc_overshoot_pct    = 100;
    cfg.rc_buf_initial_sz   = 500;
    cfg.rc_buf_optimal_sz   = 600;
    cfg.rc_buf_sz           = 1000;

    // Enable error resilient mode
    cfg.g_error_resilient = 1;
    cfg.g_lag_in_frames   = 0;
    cfg.kf_mode           = VPX_KF_DISABLED;

    // Disable automatic keyframe placement
    cfg.kf_min_dist = cfg.kf_max_dist = 1000;

    // Temporal scaling parameters:
    // NOTE: The 3 prediction frames cannot be used interchangeably due to
    // differences in the way they are handled throughout the code. The
    // frames should be allocated to layers in the order LAST, GF, ARF.
    // Other combinations work, but may produce slightly inferior results.
    switch (layering_mode)
    {

    case 0:
    {
        // 2-layers, 2-frame period
        int ids[2] = {0,1};
        cfg.ts_number_layers     = 2;
        cfg.ts_periodicity       = 2;
        cfg.ts_rate_decimator[0] = 2;
        cfg.ts_rate_decimator[1] = 1;
        memcpy(cfg.ts_layer_id, ids, sizeof(ids));

#if 1
        // 0=L, 1=GF, Intra-layer prediction enabled
        layer_flags[0] = VPX_EFLAG_FORCE_KF  |
                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
                         VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
        layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
                         VP8_EFLAG_NO_REF_ARF;
#else
        // 0=L, 1=GF, Intra-layer prediction disabled
        layer_flags[0] = VPX_EFLAG_FORCE_KF  |
                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
                         VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
        layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
                         VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_LAST;
#endif
        break;
    }

    case 1:
    {
        // 2-layers, 3-frame period
        int ids[3] = {0,1,1};
        cfg.ts_number_layers     = 2;
        cfg.ts_periodicity       = 3;
        cfg.ts_rate_decimator[0] = 3;
        cfg.ts_rate_decimator[1] = 1;
        memcpy(cfg.ts_layer_id, ids, sizeof(ids));

        // 0=L, 1=GF, Intra-layer prediction enabled
        layer_flags[0] = VPX_EFLAG_FORCE_KF  |
                         VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
        layer_flags[1] =
        layer_flags[2] = VP8_EFLAG_NO_REF_GF  |
                         VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF |
                                                VP8_EFLAG_NO_UPD_LAST;
        break;
    }

    case 2:
    {
        // 3-layers, 6-frame period
        int ids[6] = {0,2,2,1,2,2};
        cfg.ts_number_layers     = 3;
        cfg.ts_periodicity       = 6;
        cfg.ts_rate_decimator[0] = 6;
        cfg.ts_rate_decimator[1] = 3;
        cfg.ts_rate_decimator[2] = 1;
        memcpy(cfg.ts_layer_id, ids, sizeof(ids));

        // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled
        layer_flags[0] = VPX_EFLAG_FORCE_KF  |
                         VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
        layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF |
                                                VP8_EFLAG_NO_UPD_LAST;
        layer_flags[1] =
        layer_flags[2] =
        layer_flags[4] =
        layer_flags[5] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
        break;
    }

    case 3:
    {
        // 3-layers, 4-frame period
        int ids[4] = {0,2,1,2};
        cfg.ts_number_layers     = 3;
        cfg.ts_periodicity       = 4;
        cfg.ts_rate_decimator[0] = 4;
        cfg.ts_rate_decimator[1] = 2;
        cfg.ts_rate_decimator[2] = 1;
        memcpy(cfg.ts_layer_id, ids, sizeof(ids));

        // 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled
        layer_flags[0] = VPX_EFLAG_FORCE_KF  |
                         VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
        layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
                         VP8_EFLAG_NO_UPD_ARF |
                         VP8_EFLAG_NO_UPD_LAST;
        layer_flags[1] =
        layer_flags[3] = VP8_EFLAG_NO_REF_ARF |
                         VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
                         VP8_EFLAG_NO_UPD_ARF;
        break;
    }

    case 4:
    {
        // 3-layers, 4-frame period
        int ids[4] = {0,2,1,2};
        cfg.ts_number_layers     = 3;
        cfg.ts_periodicity       = 4;
        cfg.ts_rate_decimator[0] = 4;
        cfg.ts_rate_decimator[1] = 2;
        cfg.ts_rate_decimator[2] = 1;
        memcpy(cfg.ts_layer_id, ids, sizeof(ids));

        // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled in layer 1,
        // disabled in layer 2
        layer_flags[0] = VPX_EFLAG_FORCE_KF  |
                         VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
        layer_flags[2] = VP8_EFLAG_NO_REF_ARF |
                         VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
        layer_flags[1] =
        layer_flags[3] = VP8_EFLAG_NO_REF_ARF |
                         VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
                         VP8_EFLAG_NO_UPD_ARF;
        break;
    }

    case 5:
    {
        // 3-layers, 4-frame period
        int ids[4] = {0,2,1,2};
        cfg.ts_number_layers     = 3;
        cfg.ts_periodicity       = 4;
        cfg.ts_rate_decimator[0] = 4;
        cfg.ts_rate_decimator[1] = 2;
        cfg.ts_rate_decimator[2] = 1;
        memcpy(cfg.ts_layer_id, ids, sizeof(ids));

        // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled
        layer_flags[0] = VPX_EFLAG_FORCE_KF  |
                         VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
        layer_flags[2] = VP8_EFLAG_NO_REF_ARF |
                         VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
        layer_flags[1] =
        layer_flags[3] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
        break;
    }

    case 6:
    {
        // NOTE: Probably of academic interest only

        // 5-layers, 16-frame period
        int ids[16] = {0,4,3,4,2,4,3,4,1,4,3,4,2,4,3,4};
        cfg.ts_number_layers     = 5;
        cfg.ts_periodicity       = 16;
        cfg.ts_rate_decimator[0] = 16;
        cfg.ts_rate_decimator[1] = 8;
        cfg.ts_rate_decimator[2] = 4;
        cfg.ts_rate_decimator[3] = 2;
        cfg.ts_rate_decimator[4] = 1;
        memcpy(cfg.ts_layer_id, ids, sizeof(ids));

        layer_flags[0]  = VPX_EFLAG_FORCE_KF;
        layer_flags[1]  =
        layer_flags[3]  =
        layer_flags[5]  =
        layer_flags[7]  =
        layer_flags[9]  =
        layer_flags[11] =
        layer_flags[13] =
        layer_flags[15] = VP8_EFLAG_NO_UPD_LAST |
                          VP8_EFLAG_NO_UPD_GF   |
                          VP8_EFLAG_NO_UPD_ARF  |
                          VP8_EFLAG_NO_UPD_ENTROPY;
        layer_flags[2]  =
        layer_flags[6]  =
        layer_flags[10] =
        layer_flags[14] = 0;
        layer_flags[4]  =
        layer_flags[12] = VP8_EFLAG_NO_REF_LAST;
        layer_flags[8]  = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF |
                          VP8_EFLAG_NO_UPD_ENTROPY;
        break;
    }

    default:
        break;
    }

    // Open input file
    if(!(infile = fopen(argv[1], "rb")))
        die("Failed to open %s for reading", argv[1]);

    // Open an output file for each stream
    for (i=0; i<cfg.ts_number_layers; i++)
    {
        char file_name[512];
        sprintf (file_name, "%s_%d.ivf", argv[2], i);
        if (!(outfile[i] = fopen(file_name, "wb")))
            die("Failed to open %s for writing", file_name);
        write_ivf_file_header(outfile[i], &cfg, 0);
    }

    // Initialize codec
    if (vpx_codec_enc_init (&codec, interface, &cfg, 0))
        die_codec (&codec, "Failed to initialize encoder");

    // Cap CPU & first I-frame size
    vpx_codec_control (&codec, VP8E_SET_CPUUSED, -6);
    vpx_codec_control (&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT, 600);

    frame_avail = 1;
    while (frame_avail || got_data) {
        vpx_codec_iter_t iter = NULL;
        const vpx_codec_cx_pkt_t *pkt;

        flags = layer_flags[frame_cnt % cfg.ts_periodicity];

        frame_avail = read_frame(infile, &raw);
        if (vpx_codec_encode(&codec, frame_avail? &raw : NULL, pts,
                            1, flags, VPX_DL_REALTIME))
            die_codec(&codec, "Failed to encode frame");

        // Reset KF flag
        layer_flags[0] &= ~VPX_EFLAG_FORCE_KF;

        got_data = 0;
        while ( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
            got_data = 1;
            switch (pkt->kind) {
            case VPX_CODEC_CX_FRAME_PKT:
                for (i=cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
                                              i<cfg.ts_number_layers; i++)
                {
                    write_ivf_frame_header(outfile[i], pkt);
                    if (fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
                              outfile[i]));
                    frames_in_layer[i]++;
                }
                break;
            default:
                break;
            }
            printf (pkt->kind == VPX_CODEC_CX_FRAME_PKT
                    && (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
            fflush (stdout);
        }
        frame_cnt++;
        pts += frame_duration;
    }
    printf ("\n");
    fclose (infile);

    printf ("Processed %d frames.\n",frame_cnt-1);
    if (vpx_codec_destroy(&codec))
            die_codec (&codec, "Failed to destroy codec");

    // Try to rewrite the output file headers with the actual frame count
    for (i=0; i<cfg.ts_number_layers; i++)
    {
        if (!fseek(outfile[i], 0, SEEK_SET))
            write_ivf_file_header (outfile[i], &cfg, frames_in_layer[i]);
        fclose (outfile[i]);
    }

    return EXIT_SUCCESS;
}
Esempio n. 17
0
int main(int argc, char **argv) {
  FILE *infile = NULL;
  int w, h;
  vpx_codec_ctx_t codec;
  vpx_codec_enc_cfg_t cfg;
  vpx_image_t raw;
  vpx_codec_err_t res;
  vpx_fixed_buf_t stats;

  const VpxInterface *encoder = NULL;
  const int fps = 30;       // TODO(dkovalev) add command line argument
  const int bitrate = 200;  // kbit/s TODO(dkovalev) add command line argument
  const char *const codec_arg = argv[1];
  const char *const width_arg = argv[2];
  const char *const height_arg = argv[3];
  const char *const infile_arg = argv[4];
  const char *const outfile_arg = argv[5];
  exec_name = argv[0];

  if (argc != 6) die("Invalid number of arguments.");

  encoder = get_vpx_encoder_by_name(codec_arg);
  if (!encoder) die("Unsupported codec.");

  w = strtol(width_arg, NULL, 0);
  h = strtol(height_arg, NULL, 0);

  if (w <= 0 || h <= 0 || (w % 2) != 0 || (h % 2) != 0)
    die("Invalid frame size: %dx%d", w, h);

  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, w, h, 1))
    die("Failed to allocate image", w, h);

  printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));

  // Configuration
  res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
  if (res) die_codec(&codec, "Failed to get default codec config.");

  cfg.g_w = w;
  cfg.g_h = h;
  cfg.g_timebase.num = 1;
  cfg.g_timebase.den = fps;
  cfg.rc_target_bitrate = bitrate;

  if (!(infile = fopen(infile_arg, "rb")))
    die("Failed to open %s for reading", infile_arg);

  // Pass 0
  cfg.g_pass = VPX_RC_FIRST_PASS;
  stats = pass0(&raw, infile, encoder, &cfg);

  // Pass 1
  rewind(infile);
  cfg.g_pass = VPX_RC_LAST_PASS;
  cfg.rc_twopass_stats_in = stats;
  pass1(&raw, infile, outfile_arg, encoder, &cfg);
  free(stats.buf);

  vpx_img_free(&raw);
  fclose(infile);

  return EXIT_SUCCESS;
}
// Prepare to compress frames.
// Compressor should record session and sessionOptions for use in later calls.
// Compressor may modify imageDescription at this point.
// Compressor may create and return pixel buffer options.
ComponentResult
VP8_Encoder_PrepareToCompressFrames(
                                    VP8EncoderGlobals glob,
                                    ICMCompressorSessionRef session,
                                    ICMCompressionSessionOptionsRef sessionOptions,
                                    ImageDescriptionHandle imageDescription,
                                    void *reserved,
                                    CFDictionaryRef *compressorPixelBufferAttributesOut)
{
  dbg_printf("[vp8e] Prepare to Compress Frames\n", (UInt32)glob);
  ComponentResult err = noErr;
  CFMutableDictionaryRef compressorPixelBufferAttributes = NULL;
  //This format later needs to be converted
  OSType pixelFormatList[] = { k422YpCbCr8PixelFormat }; // also known as '2vuy'

  Fixed gammaLevel;
  int frameIndex;
  SInt32 widthRoundedUp, heightRoundedUp;

  // Record the compressor session for later calls to the ICM.
  // Note: this is NOT a CF type and should NOT be CFRetained or CFReleased.
  glob->session = session;

  // Retain the session options for later use.
  ICMCompressionSessionOptionsRelease(glob->sessionOptions);
  glob->sessionOptions = sessionOptions;
  ICMCompressionSessionOptionsRetain(glob->sessionOptions);

  // Modify imageDescription here if needed.
  // We'll set the image description gamma level to say "2.2".
  gammaLevel = kQTCCIR601VideoGammaLevel;
  err = ICMImageDescriptionSetProperty(imageDescription,
                                       kQTPropertyClass_ImageDescription,
                                       kICMImageDescriptionPropertyID_GammaLevel,
                                       sizeof(gammaLevel),
                                       &gammaLevel);

  if (err)
    goto bail;

  // Record the dimensions from the image description.
  glob->width = (*imageDescription)->width;
  glob->height = (*imageDescription)->height;
  dbg_printf("[vp8e - %08lx] Prepare to compress frame width %d height %d\n", (UInt32)glob, glob->width, glob->height);

  if (glob->width < 16 || glob->width % 2 || glob->height < 16 || glob->height % 2)
    dbg_printf("[vp8e - %08lx] Warning :: Invalid resolution: %ldx%ld", (UInt32)glob, glob->width, glob->height);

  if (glob->raw == NULL)
    glob->raw = calloc(1, sizeof(vpx_image_t));

  //Right now I'm only using YV12, this is great for webm, as I control the spit component
  if (!vpx_img_alloc(glob->raw, IMG_FMT_YV12, glob->width, glob->height, 1))
  {
    dbg_printf("[vp8e - %08lx] Error: Failed to allocate image %dx%d", (UInt32)glob, glob->width, glob->height);
    err = paramErr;
    goto bail;
  }

  glob->maxEncodedDataSize = glob->width * glob->height * 2;
  dbg_printf("[vp8e - %08lx] currently allocating %d bytes as my max encoded size\n", (UInt32)glob, glob->maxEncodedDataSize);

  // Create a pixel buffer attributes dictionary.
  err = createPixelBufferAttributesDictionary(glob->width, glob->height,
                                              pixelFormatList, sizeof(pixelFormatList) / sizeof(OSType),
                                              &compressorPixelBufferAttributes);

  if (err)
    goto bail;

  *compressorPixelBufferAttributesOut = compressorPixelBufferAttributes;
  compressorPixelBufferAttributes = NULL;

  /* Populate encoder configuration */
  glob->res = vpx_codec_enc_config_default((&vpx_codec_vp8_cx_algo), &glob->cfg, 0);

  if (glob->res)
  {
    dbg_printf("[vp8e - %08lx] Failed to get config: %s\n", (UInt32)glob, vpx_codec_err_to_string(glob->res));
    err = paramErr; //this may be something different ....
    goto bail;
  }

  glob->cfg.g_w = glob->width;
  glob->cfg.g_h = glob->height;
  dbg_printf("[vp8e - %08lx] resolution %dx%d\n", (UInt32)glob,
             glob->cfg.g_w, glob->cfg.g_h);

bail:

  if (err)
    dbg_printf("[vp8e - %08lx] Error %d\n", (UInt32)glob, err);

  if (compressorPixelBufferAttributes) CFRelease(compressorPixelBufferAttributes);

  return err;
}
Esempio n. 19
0
int main(int argc, char **argv) {
  VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = {NULL};
  vpx_codec_ctx_t codec;
  vpx_codec_enc_cfg_t cfg;
  int frame_cnt = 0;
  vpx_image_t raw;
  vpx_codec_err_t res;
  unsigned int width;
  unsigned int height;
  int speed;
  int frame_avail;
  int got_data;
  int flags = 0;
  unsigned int i;
  int pts = 0;  // PTS starts at 0.
  int frame_duration = 1;  // 1 timebase tick per frame.
  int layering_mode = 0;
  int layer_flags[VPX_TS_MAX_PERIODICITY] = {0};
  int flag_periodicity = 1;
#if VPX_ENCODER_ABI_VERSION > (4 + VPX_CODEC_ABI_VERSION)
  vpx_svc_layer_id_t layer_id = {0, 0};
#else
  vpx_svc_layer_id_t layer_id = {0};
#endif
  const VpxInterface *encoder = NULL;
  FILE *infile = NULL;
  struct RateControlMetrics rc;
  int64_t cx_time = 0;
  const int min_args_base = 11;
#if CONFIG_VP9_HIGHBITDEPTH
  vpx_bit_depth_t bit_depth = VPX_BITS_8;
  int input_bit_depth = 8;
  const int min_args = min_args_base + 1;
#else
  const int min_args = min_args_base;
#endif  // CONFIG_VP9_HIGHBITDEPTH
  double sum_bitrate = 0.0;
  double sum_bitrate2 = 0.0;
  double framerate  = 30.0;

  exec_name = argv[0];
  // Check usage and arguments.
  if (argc < min_args) {
#if CONFIG_VP9_HIGHBITDEPTH
    die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> "
        "<rate_num> <rate_den> <speed> <frame_drop_threshold> <mode> "
        "<Rate_0> ... <Rate_nlayers-1> <bit-depth> \n", argv[0]);
#else
    die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> "
        "<rate_num> <rate_den> <speed> <frame_drop_threshold> <mode> "
        "<Rate_0> ... <Rate_nlayers-1> \n", argv[0]);
#endif  // CONFIG_VP9_HIGHBITDEPTH
  }

  encoder = get_vpx_encoder_by_name(argv[3]);
  if (!encoder)
    die("Unsupported codec.");

  printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));

  width = strtol(argv[4], NULL, 0);
  height = strtol(argv[5], NULL, 0);
  if (width < 16 || width % 2 || height < 16 || height % 2) {
    die("Invalid resolution: %d x %d", width, height);
  }

  layering_mode = strtol(argv[10], NULL, 0);
  if (layering_mode < 0 || layering_mode > 12) {
    die("Invalid layering mode (0..12) %s", argv[10]);
  }

  if (argc != min_args + mode_to_num_layers[layering_mode]) {
    die("Invalid number of arguments");
  }

#if CONFIG_VP9_HIGHBITDEPTH
  switch (strtol(argv[argc-1], NULL, 0)) {
    case 8:
      bit_depth = VPX_BITS_8;
      input_bit_depth = 8;
      break;
    case 10:
      bit_depth = VPX_BITS_10;
      input_bit_depth = 10;
      break;
    case 12:
      bit_depth = VPX_BITS_12;
      input_bit_depth = 12;
      break;
    default:
      die("Invalid bit depth (8, 10, 12) %s", argv[argc-1]);
  }
  if (!vpx_img_alloc(&raw,
                     bit_depth == VPX_BITS_8 ? VPX_IMG_FMT_I420 :
                                               VPX_IMG_FMT_I42016,
                     width, height, 32)) {
    die("Failed to allocate image", width, height);
  }
#else
  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 32)) {
    die("Failed to allocate image", width, height);
  }
#endif  // CONFIG_VP9_HIGHBITDEPTH

  // Populate encoder configuration.
  res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
  if (res) {
    printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
    return EXIT_FAILURE;
  }

  // Update the default configuration with our settings.
  cfg.g_w = width;
  cfg.g_h = height;

#if CONFIG_VP9_HIGHBITDEPTH
  if (bit_depth != VPX_BITS_8) {
    cfg.g_bit_depth = bit_depth;
    cfg.g_input_bit_depth = input_bit_depth;
    cfg.g_profile = 2;
  }
#endif  // CONFIG_VP9_HIGHBITDEPTH

  // Timebase format e.g. 30fps: numerator=1, demoninator = 30.
  cfg.g_timebase.num = strtol(argv[6], NULL, 0);
  cfg.g_timebase.den = strtol(argv[7], NULL, 0);

  speed = strtol(argv[8], NULL, 0);
  if (speed < 0) {
    die("Invalid speed setting: must be positive");
  }

  for (i = min_args_base;
       (int)i < min_args_base + mode_to_num_layers[layering_mode];
       ++i) {
    rc.layer_target_bitrate[i - 11] = strtol(argv[i], NULL, 0);
    if (strncmp(encoder->name, "vp8", 3) == 0)
      cfg.ts_target_bitrate[i - 11] = rc.layer_target_bitrate[i - 11];
    else if (strncmp(encoder->name, "vp9", 3) == 0)
      cfg.layer_target_bitrate[i - 11] = rc.layer_target_bitrate[i - 11];
  }

  // Real time parameters.
  cfg.rc_dropframe_thresh = strtol(argv[9], NULL, 0);
  cfg.rc_end_usage = VPX_CBR;
  cfg.rc_min_quantizer = 2;
  cfg.rc_max_quantizer = 56;
  if (strncmp(encoder->name, "vp9", 3) == 0)
    cfg.rc_max_quantizer = 52;
  cfg.rc_undershoot_pct = 50;
  cfg.rc_overshoot_pct = 50;
  cfg.rc_buf_initial_sz = 500;
  cfg.rc_buf_optimal_sz = 600;
  cfg.rc_buf_sz = 1000;

  // Disable dynamic resizing by default.
  cfg.rc_resize_allowed = 0;

  // Use 1 thread as default.
  cfg.g_threads = 1;

  // Enable error resilient mode.
  cfg.g_error_resilient = 1;
  cfg.g_lag_in_frames   = 0;
  cfg.kf_mode = VPX_KF_AUTO;

  // Disable automatic keyframe placement.
  cfg.kf_min_dist = cfg.kf_max_dist = 3000;

  cfg.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;

  set_temporal_layer_pattern(layering_mode,
                             &cfg,
                             layer_flags,
                             &flag_periodicity);

  set_rate_control_metrics(&rc, &cfg);

  // Target bandwidth for the whole stream.
  // Set to layer_target_bitrate for highest layer (total bitrate).
  cfg.rc_target_bitrate = rc.layer_target_bitrate[cfg.ts_number_layers - 1];

  // Open input file.
  if (!(infile = fopen(argv[1], "rb"))) {
    die("Failed to open %s for reading", argv[1]);
  }

  framerate = cfg.g_timebase.den / cfg.g_timebase.num;
  // Open an output file for each stream.
  for (i = 0; i < cfg.ts_number_layers; ++i) {
    char file_name[PATH_MAX];
    VpxVideoInfo info;
    info.codec_fourcc = encoder->fourcc;
    info.frame_width = cfg.g_w;
    info.frame_height = cfg.g_h;
    info.time_base.numerator = cfg.g_timebase.num;
    info.time_base.denominator = cfg.g_timebase.den;

    snprintf(file_name, sizeof(file_name), "%s_%d.ivf", argv[2], i);
    outfile[i] = vpx_video_writer_open(file_name, kContainerIVF, &info);
    if (!outfile[i])
      die("Failed to open %s for writing", file_name);

    assert(outfile[i] != NULL);
  }
  // No spatial layers in this encoder.
  cfg.ss_number_layers = 1;

  // Initialize codec.
#if CONFIG_VP9_HIGHBITDEPTH
  if (vpx_codec_enc_init(
          &codec, encoder->codec_interface(), &cfg,
          bit_depth == VPX_BITS_8 ? 0 : VPX_CODEC_USE_HIGHBITDEPTH))
#else
  if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
#endif  // CONFIG_VP9_HIGHBITDEPTH
    die_codec(&codec, "Failed to initialize encoder");

  // configuration for vp8/vp9
  if (strncmp(encoder->name, "vp8", 3) == 0) {
    vpx_codec_control(&codec, VP8E_SET_CPUUSED, -speed);
    vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, kDenoiserOff);
    vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 0);
  } else if (strncmp(encoder->name, "vp9", 3) == 0) {
    vpx_svc_extra_cfg_t svc_params;
    vpx_codec_control(&codec, VP8E_SET_CPUUSED, speed);
    vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3);
    vpx_codec_control(&codec, VP9E_SET_FRAME_PERIODIC_BOOST, 0);
    vpx_codec_control(&codec, VP9E_SET_NOISE_SENSITIVITY, 0);
    vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 0);
    vpx_codec_control(&codec, VP9E_SET_TUNE_CONTENT, 0);
    vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (cfg.g_threads >> 1));
    if (vpx_codec_control(&codec, VP9E_SET_SVC, layering_mode > 0 ? 1: 0))
      die_codec(&codec, "Failed to set SVC");
    for (i = 0; i < cfg.ts_number_layers; ++i) {
      svc_params.max_quantizers[i] = cfg.rc_max_quantizer;
      svc_params.min_quantizers[i] = cfg.rc_min_quantizer;
    }
    svc_params.scaling_factor_num[0] = cfg.g_h;
    svc_params.scaling_factor_den[0] = cfg.g_h;
    vpx_codec_control(&codec, VP9E_SET_SVC_PARAMETERS, &svc_params);
  }
int main(int argc, char **argv) {

    FILE *infile, *outfile;
    vpx_codec_ctx_t codec;
    vpx_codec_enc_cfg_t cfg;
    int frame_cnt = 0;
    unsigned char file_hdr[IVF_FILE_HDR_SZ];
    unsigned char frame_hdr[IVF_FRAME_HDR_SZ];
    vpx_image_t raw;
    vpx_codec_err_t ret;
    int width,height;
	int y_size;
    int frame_avail;
    int got_data;
    int flags = 0;
 
    width = 640;
    height = 360;

	infile = fopen("../cuc_ieschool_640x360_yuv420p.yuv", "rb");
	outfile = fopen("cuc_ieschool.ivf", "wb");

	if(infile==NULL||outfile==NULL){
		printf("Error open files.\n");
		return -1;
	}

	if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1)){
        printf("Fail to allocate image\n");
		return -1;
	}

    printf("Using %s\n",vpx_codec_iface_name(interface));

    //Populate encoder configuration 
    ret = vpx_codec_enc_config_default(interface, &cfg, 0);
    if(ret) {
        printf("Failed to get config: %s\n", vpx_codec_err_to_string(ret));
        return -1;                                                  
    }

    cfg.rc_target_bitrate =800;
    cfg.g_w = width;                                                          
    cfg.g_h = height;                                                         
 
    write_ivf_file_header(outfile, &cfg, 0);
 
    //Initialize codec                                              
    if(vpx_codec_enc_init(&codec, interface, &cfg, 0)){
        printf("Failed to initialize encoder\n");
		return -1;
	}
 
    frame_avail = 1;
    got_data = 0;

	y_size=cfg.g_w*cfg.g_h;

    while(frame_avail || got_data) {
        vpx_codec_iter_t iter = NULL;
        const vpx_codec_cx_pkt_t *pkt;
		
		if(fread(raw.planes[0], 1, y_size*3/2, infile)!=y_size*3/2){
			frame_avail=0;
		}

		if(frame_avail){
			//Encode
			ret=vpx_codec_encode(&codec,&raw,frame_cnt,1,flags,VPX_DL_REALTIME);
		}else{
			//Flush Encoder
			ret=vpx_codec_encode(&codec,NULL,frame_cnt,1,flags,VPX_DL_REALTIME);
		}

		if(ret){
            printf("Failed to encode frame\n");
			return -1;
		}
        got_data = 0;
        while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
            got_data = 1;
            switch(pkt->kind) {
            case VPX_CODEC_CX_FRAME_PKT:
                write_ivf_frame_header(outfile, pkt);
                fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,outfile); 
                break; 
            default:
                break;
            }
        }
		printf("Succeed encode frame: %5d\n",frame_cnt);
        frame_cnt++;
    }

    fclose(infile);
 
    vpx_codec_destroy(&codec);
 
    //Try to rewrite the file header with the actual frame count
    if(!fseek(outfile, 0, SEEK_SET))
        write_ivf_file_header(outfile, &cfg, frame_cnt-1);

    fclose(outfile);

    return 0;
}
Esempio n. 21
0
int main(int argc, char **argv) {
  FILE *infile = NULL;
  vpx_codec_ctx_t codec;
  vpx_codec_enc_cfg_t cfg;
  int frame_count = 0;
  vpx_image_t raw;
  vpx_codec_err_t res;
  VpxVideoInfo info;
  VpxVideoWriter *writer = NULL;
  const VpxInterface *encoder = NULL;
  const int fps = 2;        // TODO(dkovalev) add command line argument
  const double bits_per_pixel_per_frame = 0.067;

  exec_name = argv[0];
  if (argc != 6)
    die("Invalid number of arguments");

  memset(&info, 0, sizeof(info));

  encoder = get_vpx_encoder_by_name(argv[1]);
  if (encoder == NULL) {
    die("Unsupported codec.");
  }
  assert(encoder != NULL);
  info.codec_fourcc = encoder->fourcc;
  info.frame_width = strtol(argv[2], NULL, 0);
  info.frame_height = strtol(argv[3], NULL, 0);
  info.time_base.numerator = 1;
  info.time_base.denominator = fps;

  if (info.frame_width <= 0 ||
      info.frame_height <= 0 ||
      (info.frame_width % 2) != 0 ||
      (info.frame_height % 2) != 0) {
    die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
  }

  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
                                             info.frame_height, 1)) {
    die("Failed to allocate image.");
  }

  printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));

  res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
  if (res)
    die_codec(&codec, "Failed to get default codec config.");

  cfg.g_w = info.frame_width;
  cfg.g_h = info.frame_height;
  cfg.g_timebase.num = info.time_base.numerator;
  cfg.g_timebase.den = info.time_base.denominator;
  cfg.rc_target_bitrate = (unsigned int)(bits_per_pixel_per_frame * cfg.g_w *
                                         cfg.g_h * fps / 1000);
  cfg.g_lag_in_frames = 0;

  writer = vpx_video_writer_open(argv[5], kContainerIVF, &info);
  if (!writer)
    die("Failed to open %s for writing.", argv[5]);

  if (!(infile = fopen(argv[4], "rb")))
    die("Failed to open %s for reading.", argv[4]);

  if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
    die_codec(&codec, "Failed to initialize encoder");

  // Encode frames.
  while (vpx_img_read(&raw, infile)) {
    ++frame_count;

    if (frame_count == 22 && encoder->fourcc == VP8_FOURCC) {
      set_roi_map(&cfg, &codec);
    } else if (frame_count == 33) {
      set_active_map(&cfg, &codec);
    } else if (frame_count == 44) {
      unset_active_map(&cfg, &codec);
    }

    encode_frame(&codec, &raw, frame_count, writer);
  }

  // Flush encoder.
  while (encode_frame(&codec, NULL, -1, writer)) {}

  printf("\n");
  fclose(infile);
  printf("Processed %d frames.\n", frame_count);

  vpx_img_free(&raw);
  if (vpx_codec_destroy(&codec))
    die_codec(&codec, "Failed to destroy codec.");

  vpx_video_writer_close(writer);

  return EXIT_SUCCESS;
}
Esempio n. 22
0
int main(int argc, char **argv) {
  FILE *infile = NULL;
  // Encoder
  vpx_codec_ctx_t ecodec = {0};
  vpx_codec_enc_cfg_t cfg = {0};
  unsigned int frame_in = 0;
  vpx_image_t raw;
  vpx_codec_err_t res;
  VpxVideoInfo info = {0};
  VpxVideoWriter *writer = NULL;
  const VpxInterface *encoder = NULL;

  // Test encoder/decoder mismatch.
  int test_decode = 1;
  // Decoder
  vpx_codec_ctx_t dcodec;
  unsigned int frame_out = 0;

  // The frame number to set reference frame on
  unsigned int update_frame_num = 0;
  int mismatch_seen = 0;

  const int fps = 30;
  const int bitrate = 500;

  const char *width_arg = NULL;
  const char *height_arg = NULL;
  const char *infile_arg = NULL;
  const char *outfile_arg = NULL;
  unsigned int limit = 0;
  exec_name = argv[0];

  if (argc < 6)
    die("Invalid number of arguments");

  width_arg = argv[1];
  height_arg = argv[2];
  infile_arg = argv[3];
  outfile_arg = argv[4];

  encoder = get_vpx_encoder_by_name("vp9");
  if (!encoder)
    die("Unsupported codec.");

  update_frame_num = atoi(argv[5]);
  // In VP9, the reference buffers (cm->buffer_pool->frame_bufs[i].buf) are
  // allocated while calling vpx_codec_encode(), thus, setting reference for
  // 1st frame isn't supported.
  if (update_frame_num <= 1)
    die("Couldn't parse frame number '%s'\n", argv[5]);

  if (argc > 6) {
    limit = atoi(argv[6]);
    if (update_frame_num > limit)
      die("Update frame number couldn't larger than limit\n");
  }

  info.codec_fourcc = encoder->fourcc;
  info.frame_width = strtol(width_arg, NULL, 0);
  info.frame_height = strtol(height_arg, NULL, 0);
  info.time_base.numerator = 1;
  info.time_base.denominator = fps;

  if (info.frame_width <= 0 ||
      info.frame_height <= 0 ||
      (info.frame_width % 2) != 0 ||
      (info.frame_height % 2) != 0) {
    die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
  }

  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
                                             info.frame_height, 1)) {
    die("Failed to allocate image.");
  }

  printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));

  res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
  if (res)
    die_codec(&ecodec, "Failed to get default codec config.");

  cfg.g_w = info.frame_width;
  cfg.g_h = info.frame_height;
  cfg.g_timebase.num = info.time_base.numerator;
  cfg.g_timebase.den = info.time_base.denominator;
  cfg.rc_target_bitrate = bitrate;
  cfg.g_lag_in_frames = 3;

  writer = vpx_video_writer_open(outfile_arg, kContainerIVF, &info);
  if (!writer)
    die("Failed to open %s for writing.", outfile_arg);

  if (!(infile = fopen(infile_arg, "rb")))
    die("Failed to open %s for reading.", infile_arg);

  if (vpx_codec_enc_init(&ecodec, encoder->codec_interface(), &cfg, 0))
    die_codec(&ecodec, "Failed to initialize encoder");

  // Disable alt_ref.
  if (vpx_codec_control(&ecodec, VP8E_SET_ENABLEAUTOALTREF, 0))
    die_codec(&ecodec, "Failed to set enable auto alt ref");

  if (test_decode) {
      const VpxInterface *decoder = get_vpx_decoder_by_name("vp9");
      if (vpx_codec_dec_init(&dcodec, decoder->codec_interface(), NULL, 0))
        die_codec(&dcodec, "Failed to initialize decoder.");
  }

  // Encode frames.
  while (vpx_img_read(&raw, infile)) {
    if (limit && frame_in >= limit)
      break;
    if (update_frame_num > 1 && frame_out + 1 == update_frame_num) {
      vpx_ref_frame_t ref;
      ref.frame_type = VP8_LAST_FRAME;
      ref.img = raw;
      // Set reference frame in encoder.
      if (vpx_codec_control(&ecodec, VP8_SET_REFERENCE, &ref))
        die_codec(&ecodec, "Failed to set reference frame");
      printf(" <SET_REF>");

      // If set_reference in decoder is commented out, the enc/dec mismatch
      // would be seen.
      if (test_decode) {
        if (vpx_codec_control(&dcodec, VP8_SET_REFERENCE, &ref))
          die_codec(&dcodec, "Failed to set reference frame");
      }
    }

    encode_frame(&ecodec, &cfg, &raw, frame_in, writer, test_decode,
                 &dcodec, &frame_out, &mismatch_seen);
    frame_in++;
    if (mismatch_seen)
      break;
  }

  // Flush encoder.
  if (!mismatch_seen)
    while (encode_frame(&ecodec, &cfg, NULL, frame_in, writer, test_decode,
                        &dcodec, &frame_out, &mismatch_seen)) {}

  printf("\n");
  fclose(infile);
  printf("Processed %d frames.\n", frame_out);

  if (test_decode) {
    if (!mismatch_seen)
      printf("Encoder/decoder results are matching.\n");
    else
      printf("Encoder/decoder results are NOT matching.\n");
  }

  if (test_decode)
    if (vpx_codec_destroy(&dcodec))
      die_codec(&dcodec, "Failed to destroy decoder");

  vpx_img_free(&raw);
  if (vpx_codec_destroy(&ecodec))
    die_codec(&ecodec, "Failed to destroy encoder.");

  vpx_video_writer_close(writer);

  return EXIT_SUCCESS;
}
Esempio n. 23
0
// Initialize encoder, given setup in the encoder parameters
bool LumaEncoder::initialize(const char *outputFile, const unsigned int w, const unsigned int h, bool verbose)
{
    // Initialize base. Creates a Matroska file for writing
    LumaEncoderBase::initialize(outputFile, w, h);

    // Adjust profile for the specified bit depth (0-1 for 8 bits, and 2-3 for higher bit depths)
    if (m_params.profile > 1 && m_params.bitDepth == 8)
        m_params.profile -=2;
    if (m_params.profile < 2 && m_params.bitDepth > 8)
        m_params.profile +=2;

    // Initialize quantizer
    m_quant.setQuantizer(m_params.ptf, m_params.ptfBitDepth, m_params.colorSpace, m_params.colorBitDepth);

    // Add attachments with meta data to Matroska file
    unsigned int *buffer1 = new unsigned int;
    *buffer1 = m_params.ptfBitDepth;
    m_writer.addAttachment(430, (const binary*)buffer1, sizeof(unsigned int), "PTF bit depth");

    unsigned int *buffer2 = new unsigned int;
    *buffer2 = m_params.colorBitDepth;
    m_writer.addAttachment(431, (const binary*)buffer2, sizeof(unsigned int), "Color bit depth");

    LumaQuantizer::ptf_t *buffer3 = new LumaQuantizer::ptf_t;
    *buffer3 = m_params.ptf;
    m_writer.addAttachment(432, (const binary*)buffer3, sizeof(LumaQuantizer::ptf_t), "PTF description");

    LumaQuantizer::colorSpace_t *buffer4 = new LumaQuantizer::colorSpace_t;
    *buffer4 = m_params.colorSpace;
    m_writer.addAttachment(433, (const binary*)buffer4, sizeof(LumaQuantizer::colorSpace_t), "Color space");

    float *buffer5 = new float[m_quant.getSize()];
    memcpy((void*)buffer5, (void*)m_quant.getMapping(), (m_quant.getSize())*sizeof(float));
    m_writer.addAttachment(434, (const binary*)buffer5, (m_quant.getSize())*sizeof(float), "PTF");

    float *buffer6 = new float;
    *buffer6 = m_params.preScaling;
    m_writer.addAttachment(435, (const binary*)buffer6, sizeof(float), "Scaling");

    m_writer.writeAttachments();

    // Framerate for timecodes
    m_writer.setFramerate(m_params.fps);

    m_writer.setVerbose(verbose);

    // Initialize VPX codec
    vpx_codec_err_t res;
    vpx_codec_enc_cfg_t cfg;
    const vpx_codec_iface_t *(*const vpx_encoder)() = &vpx_codec_vp9_cx;

    if (w <= 0 || h <= 0 || (w % 2) != 0 || (h % 2) != 0)
        throw LumaException("Invalid frame size");

    if (m_params.profile == 0 && !vpx_img_alloc(&m_rawFrame, VPX_IMG_FMT_I420, w, h, 32))
        throw LumaException("Failed to allocate 8 bit 420 image");
    else if (m_params.profile == 1 && !vpx_img_alloc(&m_rawFrame, VPX_IMG_FMT_I444, w, h, 32))
        throw LumaException("Failed to allocate 8 bit 444 image");
    else if (m_params.profile == 2 && !vpx_img_alloc(&m_rawFrame, VPX_IMG_FMT_I42016, w, h, 32))
        throw LumaException("Failed to allocate 16 bit 420 image");
    else if (m_params.profile == 3 && !vpx_img_alloc(&m_rawFrame, VPX_IMG_FMT_I44416, w, h, 32))
        throw LumaException("Failed to allocate 16 bit 444 image");

    res = vpx_codec_enc_config_default(vpx_encoder(), &cfg, 0);
    if (res)
        throw LumaException("Failed to get default codec config");

    cfg.g_threads = 6;
    cfg.rc_min_quantizer = m_params.quantizerScale;
    cfg.rc_max_quantizer = m_params.quantizerScale;
    cfg.g_w = w;
    cfg.g_h = h;
    cfg.g_timebase.num = 1;
    cfg.g_timebase.den = 25;
    cfg.rc_target_bitrate = m_params.bitrate;
    cfg.g_error_resilient = 0;
    cfg.g_pass = VPX_RC_ONE_PASS;
    cfg.rc_end_usage = VPX_VBR;
    cfg.g_lag_in_frames = 0;
    cfg.rc_end_usage = VPX_Q;
    cfg.kf_max_dist = 25;
    cfg.kf_mode = VPX_KF_AUTO;
    cfg.g_profile = m_params.profile;

    fprintf(stderr, "Encoding options:\n");
    fprintf(stderr, "--------------------------------------------------------\n");
    fprintf(stderr, "Transfer function (PTF): %s\n", m_quant.name(m_params.ptf).c_str());
    fprintf(stderr, "Color space:             %s\n", m_quant.name(m_params.colorSpace).c_str());
    fprintf(stderr, "PTF bit depth:           %d\n", m_params.ptfBitDepth);
    fprintf(stderr, "Color bit depth:         %d\n", m_params.colorBitDepth);
    fprintf(stderr, "Encoding profile:        %d (4%d%d)\n", m_params.profile, (m_params.profile%2==0) ? 2 : 4, (m_params.profile%2==0) ? 2 : 4);
    fprintf(stderr, "Encoding bit depth:      ");
    if (m_params.bitDepth == 8 || m_params.profile < 2)
    {
        cfg.g_bit_depth = VPX_BITS_8;
        fprintf(stderr, "8\n");
    }
    else if (m_params.bitDepth == 10)
    {
        cfg.g_bit_depth = VPX_BITS_10;
        fprintf(stderr, "10\n");
    }
    else
    {
        cfg.g_bit_depth = VPX_BITS_12;
        fprintf(stderr, "12\n");
    }
    fprintf(stderr, "Codec:                   %s\n", vpx_codec_iface_name(vpx_encoder()));
    fprintf(stderr, "Output:                  %s\n", outputFile);
    fprintf(stderr, "--------------------------------------------------------\n\n");

    int flags = m_params.profile < 2 ? 0 : VPX_CODEC_USE_HIGHBITDEPTH;
    if (vpx_codec_enc_init(&m_codec, vpx_encoder(), &cfg, flags))
        throw LumaException("Failed to initialize vpxEncoder\n");

    if (m_params.lossLess && vpx_codec_control_(&m_codec, VP9E_SET_LOSSLESS, 1))
        throw LumaException("Failed to use lossless mode\n");

    m_initialized = true;
    return true;
}
int main(int argc, const char **argv) {
    AppInput app_input = {0};
    FILE *outfile;
    vpx_codec_ctx_t codec;
    vpx_codec_enc_cfg_t enc_cfg;
    SvcContext svc_ctx;
    uint32_t i;
    uint32_t frame_cnt = 0;
    vpx_image_t raw;
    vpx_codec_err_t res;
    int pts = 0;            /* PTS starts at 0 */
    int frame_duration = 1; /* 1 timebase tick per frame */
    vpx_codec_cx_pkt_t packet = {0};
    packet.kind = VPX_CODEC_CX_FRAME_PKT;

    memset(&svc_ctx, 0, sizeof(svc_ctx));
    svc_ctx.log_print = 1;
    exec_name = argv[0];
    parse_command_line(argc, argv, &app_input, &svc_ctx, &enc_cfg);

    // Allocate image buffer
    if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, enc_cfg.g_w, enc_cfg.g_h, 32))
        die("Failed to allocate image %dx%d\n", enc_cfg.g_w, enc_cfg.g_h);

    if (!(app_input.input_ctx.file = fopen(app_input.input_ctx.filename, "rb")))
        die("Failed to open %s for reading\n", app_input.input_ctx.filename);

    if (!(outfile = fopen(app_input.output_filename, "wb")))
        die("Failed to open %s for writing\n", app_input.output_filename);

    // Initialize codec
    if (vpx_svc_init(&svc_ctx, &codec, vpx_codec_vp9_cx(), &enc_cfg) !=
            VPX_CODEC_OK)
        die("Failed to initialize encoder\n");

    ivf_write_file_header(outfile, &enc_cfg, VP9_FOURCC, 0);

    // skip initial frames
    for (i = 0; i < app_input.frames_to_skip; ++i) {
        read_yuv_frame(&app_input.input_ctx, &raw);
    }

    // Encode frames
    while (frame_cnt < app_input.frames_to_code) {
        if (read_yuv_frame(&app_input.input_ctx, &raw)) break;

        res = vpx_svc_encode(&svc_ctx, &codec, &raw, pts, frame_duration,
                             VPX_DL_REALTIME);
        printf("%s", vpx_svc_get_message(&svc_ctx));
        if (res != VPX_CODEC_OK) {
            die_codec(&codec, "Failed to encode frame");
        }
        if (vpx_svc_get_frame_size(&svc_ctx) > 0) {
            packet.data.frame.pts = pts;
            packet.data.frame.sz = vpx_svc_get_frame_size(&svc_ctx);
            ivf_write_frame_header(outfile, &packet);
            (void)fwrite(vpx_svc_get_buffer(&svc_ctx), 1,
                         vpx_svc_get_frame_size(&svc_ctx), outfile);
        }
        ++frame_cnt;
        pts += frame_duration;
    }

    printf("Processed %d frames\n", frame_cnt);

    fclose(app_input.input_ctx.file);
    if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");

    // rewrite the output file headers with the actual frame count, and
    // resolution of the highest layer
    if (!fseek(outfile, 0, SEEK_SET)) {
        // get resolution of highest layer
        if (VPX_CODEC_OK != vpx_svc_get_layer_resolution(&svc_ctx,
                svc_ctx.spatial_layers - 1,
                &enc_cfg.g_w,
                &enc_cfg.g_h)) {
            die("Failed to get output resolution");
        }
        ivf_write_file_header(outfile, &enc_cfg, VP9_FOURCC, frame_cnt);
    }
    fclose(outfile);
    vpx_img_free(&raw);

    // display average size, psnr
    printf("%s", vpx_svc_dump_statistics(&svc_ctx));

    vpx_svc_release(&svc_ctx);

    return EXIT_SUCCESS;
}
Esempio n. 25
0
VideoSurface::VideoSurface()
    : QAbstractVideoSurface()
{
    vpx_img_alloc(&input, VPX_IMG_FMT_YV12, TOXAV_MAX_VIDEO_WIDTH, TOXAV_MAX_VIDEO_HEIGHT, 1);
}
Esempio n. 26
0
void *encode_video_thread(void *arg)
{
    INFO("Started encode video thread!");

    av_session_t *_phone = arg;

    _phone->running_encvid = 1;
    //CodecState *cs = get_cs_temp(_phone->av);
    AVPacket pkt1, *packet = &pkt1;
    //int p = 0;
    //int got_packet;
    int video_frame_finished;
    AVFrame *s_video_frame;
    AVFrame *webcam_frame;
    s_video_frame = avcodec_alloc_frame();
    webcam_frame = avcodec_alloc_frame();
    //AVPacket enc_video_packet;

    uint8_t *buffer;
    int numBytes;
    /* Determine required buffer size and allocate buffer */
    numBytes = avpicture_get_size(PIX_FMT_YUV420P, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height);
    buffer = (uint8_t *)av_calloc(numBytes * sizeof(uint8_t), 1);
    avpicture_fill((AVPicture *)s_video_frame, buffer, PIX_FMT_YUV420P, _phone->webcam_decoder_ctx->width,
                   _phone->webcam_decoder_ctx->height);
    _phone->sws_ctx = sws_getContext(_phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height,
                                     _phone->webcam_decoder_ctx->pix_fmt, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height,
                                     PIX_FMT_YUV420P,
                                     SWS_BILINEAR, NULL, NULL, NULL);


    vpx_image_t *image =
        vpx_img_alloc(NULL, VPX_IMG_FMT_I420, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height, 1);

    //uint32_t frame_counter = 0;
    while (_phone->running_encvid) {

        if (av_read_frame(_phone->video_format_ctx, packet) < 0) {
            printf("error reading frame\n");

            if (_phone->video_format_ctx->pb->error != 0)
                break;

            continue;
        }

        if (packet->stream_index == _phone->video_stream) {
            if (avcodec_decode_video2(_phone->webcam_decoder_ctx, webcam_frame, &video_frame_finished, packet) < 0) {
                printf("couldn't decode\n");
                continue;
            }

            av_free_packet(packet);
            sws_scale(_phone->sws_ctx, (uint8_t const * const *)webcam_frame->data, webcam_frame->linesize, 0,
                      _phone->webcam_decoder_ctx->height, s_video_frame->data, s_video_frame->linesize);
            /* create a new I-frame every 60 frames */
            //++p;
            /*
            if (p == 60) {

                s_video_frame->pict_type = AV_PICTURE_TYPE_BI ;
            } else if (p == 61) {
                s_video_frame->pict_type = AV_PICTURE_TYPE_I ;
                p = 0;
            } else {
                s_video_frame->pict_type = AV_PICTURE_TYPE_P ;
            }*/

            if (video_frame_finished) {
                memcpy(image->planes[VPX_PLANE_Y], s_video_frame->data[0],
                       s_video_frame->linesize[0] * _phone->webcam_decoder_ctx->height);
                memcpy(image->planes[VPX_PLANE_U], s_video_frame->data[1],
                       s_video_frame->linesize[1] * _phone->webcam_decoder_ctx->height / 2);
                memcpy(image->planes[VPX_PLANE_V], s_video_frame->data[2],
                       s_video_frame->linesize[2] * _phone->webcam_decoder_ctx->height / 2);
                toxav_send_video (_phone->av, image);
                //if (avcodec_encode_video2(cs->video_encoder_ctx, &enc_video_packet, s_video_frame, &got_packet) < 0) {
                /*if (vpx_codec_encode(&cs->v_encoder, image, frame_counter, 1, 0, 0) != VPX_CODEC_OK) {
                    printf("could not encode video frame\n");
                    continue;
                }
                ++frame_counter;

                vpx_codec_iter_t iter = NULL;
                vpx_codec_cx_pkt_t *pkt;
                while( (pkt = vpx_codec_get_cx_data(&cs->v_encoder, &iter)) ) {
                    if (pkt->kind == VPX_CODEC_CX_FRAME_PKT)
                        toxav_send_rtp_payload(_phone->av, TypeVideo, pkt->data.frame.buf, pkt->data.frame.sz);
                }*/
                //if (!got_packet) {
                //    continue;
                //}

                //if (!enc_video_packet.data) fprintf(stderr, "video packet data is NULL\n");

                //toxav_send_rtp_payload(_phone->av, TypeVideo, enc_video_packet.data, enc_video_packet.size);

                //av_free_packet(&enc_video_packet);
            }
        } else {
            av_free_packet(packet);
        }
    }

    vpx_img_free(image);

    /* clean up codecs */
    //pthread_mutex_lock(&cs->ctrl_mutex);
    av_free(buffer);
    av_free(webcam_frame);
    av_free(s_video_frame);
    sws_freeContext(_phone->sws_ctx);
    //avcodec_close(webcam_decoder_ctx);
    //avcodec_close(cs->video_encoder_ctx);
    //pthread_mutex_unlock(&cs->ctrl_mutex);

    _phone->running_encvid = -1;

    pthread_exit ( NULL );
}
Esempio n. 27
0
// TODO(tomfinegan): Improve command line parsing and add args for bitrate/fps.
int main(int argc, char **argv) {
  FILE *infile = NULL;
  vpx_codec_ctx_t codec;
  vpx_codec_enc_cfg_t cfg;
  int frame_count = 0;
  vpx_image_t raw;
  vpx_codec_err_t res;
  VpxVideoInfo info = { 0, 0, 0, { 0, 0 } };
  VpxVideoWriter *writer = NULL;
  const VpxInterface *encoder = NULL;
  const int fps = 30;
  const int bitrate = 200;
  int keyframe_interval = 0;
  int max_frames = 0;
  int frames_encoded = 0;
  const char *codec_arg = NULL;
  const char *width_arg = NULL;
  const char *height_arg = NULL;
  const char *infile_arg = NULL;
  const char *outfile_arg = NULL;
  const char *keyframe_interval_arg = NULL;

  exec_name = argv[0];

  if (argc != 9) die("Invalid number of arguments");

  codec_arg = argv[1];
  width_arg = argv[2];
  height_arg = argv[3];
  infile_arg = argv[4];
  outfile_arg = argv[5];
  keyframe_interval_arg = argv[6];
  max_frames = (int)strtol(argv[8], NULL, 0);

  encoder = get_vpx_encoder_by_name(codec_arg);
  if (!encoder) die("Unsupported codec.");

  info.codec_fourcc = encoder->fourcc;
  info.frame_width = (int)strtol(width_arg, NULL, 0);
  info.frame_height = (int)strtol(height_arg, NULL, 0);
  info.time_base.numerator = 1;
  info.time_base.denominator = fps;

  if (info.frame_width <= 0 || info.frame_height <= 0 ||
      (info.frame_width % 2) != 0 || (info.frame_height % 2) != 0) {
    die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
  }

  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
                     info.frame_height, 1)) {
    die("Failed to allocate image.");
  }

  keyframe_interval = (int)strtol(keyframe_interval_arg, NULL, 0);
  if (keyframe_interval < 0) die("Invalid keyframe interval value.");

  printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));

  res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
  if (res) die_codec(&codec, "Failed to get default codec config.");

  cfg.g_w = info.frame_width;
  cfg.g_h = info.frame_height;
  cfg.g_timebase.num = info.time_base.numerator;
  cfg.g_timebase.den = info.time_base.denominator;
  cfg.rc_target_bitrate = bitrate;
  cfg.g_error_resilient = (vpx_codec_er_flags_t)strtoul(argv[7], NULL, 0);

  writer = vpx_video_writer_open(outfile_arg, kContainerIVF, &info);
  if (!writer) die("Failed to open %s for writing.", outfile_arg);

  if (!(infile = fopen(infile_arg, "rb")))
    die("Failed to open %s for reading.", infile_arg);

  if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
    die_codec(&codec, "Failed to initialize encoder");

  // Encode frames.
  while (vpx_img_read(&raw, infile)) {
    int flags = 0;
    if (keyframe_interval > 0 && frame_count % keyframe_interval == 0)
      flags |= VPX_EFLAG_FORCE_KF;
    encode_frame(&codec, &raw, frame_count++, flags, writer);
    frames_encoded++;
    if (max_frames > 0 && frames_encoded >= max_frames) break;
  }

  // Flush encoder.
  while (encode_frame(&codec, NULL, -1, 0, writer)) {
  }

  printf("\n");
  fclose(infile);
  printf("Processed %d frames.\n", frame_count);

  vpx_img_free(&raw);
  if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");

  vpx_video_writer_close(writer);

  return EXIT_SUCCESS;
}
int main(int argc, char **argv) {
    FILE                *infile, *outfile;
    vpx_codec_ctx_t      codec;
    vpx_codec_enc_cfg_t  cfg;
    int                  frame_cnt = 0;
    vpx_image_t          raw;
    vpx_codec_err_t      res;
    long                 width;
    long                 height;
    int                  frame_avail;
    int                  got_data;
    int                  flags = 0;

    /* Open files */
    if(argc!=5)
        die("Usage: %s <width> <height> <infile> <outfile>\n", argv[0]);
    width = strtol(argv[1], NULL, 0);
    height = strtol(argv[2], NULL, 0);
    if(width < 16 || width%2 || height <16 || height%2)
        die("Invalid resolution: %ldx%ld", width, height);
    if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1))
        die("Faile to allocate image", width, height);
    if(!(outfile = fopen(argv[4], "wb")))
        die("Failed to open %s for writing", argv[4]);

    printf("Using %s\n",vpx_codec_iface_name(interface));

    /* Populate encoder configuration */                                      //
    res = vpx_codec_enc_config_default(interface, &cfg, 0);                   //
    if(res) {                                                                 //
        printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));   //
        return EXIT_FAILURE;                                                  //
    }                                                                         //

    /* Update the default configuration with our settings */                  //
    cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate            //
                            / cfg.g_w / cfg.g_h;                              //
    cfg.g_w = width;                                                          //
    cfg.g_h = height;                                                         //

    write_ivf_file_header(outfile, &cfg, 0);


        /* Open input file for this encoding pass */
        if(!(infile = fopen(argv[3], "rb")))
            die("Failed to open %s for reading", argv[3]);

        /* Initialize codec */                                                //
        if(vpx_codec_enc_init(&codec, interface, &cfg, 0))                    //
            die_codec(&codec, "Failed to initialize encoder");                //

        frame_avail = 1;
        got_data = 0;
        while(frame_avail || got_data) {
            vpx_codec_iter_t iter = NULL;
            const vpx_codec_cx_pkt_t *pkt;

            frame_avail = read_frame(infile, &raw);                           //
            if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,  //
                                1, flags, VPX_DL_REALTIME))                   //
                die_codec(&codec, "Failed to encode frame");                  //
            got_data = 0;
            while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
                got_data = 1;
                switch(pkt->kind) {
                case VPX_CODEC_CX_FRAME_PKT:                                  //
                    write_ivf_frame_header(outfile, pkt);                     //
                    if(fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,     //
                              outfile));                                      //
                    break;                                                    //
                default:
                    break;
                }
                printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT
                       && (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
                fflush(stdout);
            }
            frame_cnt++;
        }
        printf("\n");
        fclose(infile);

    printf("Processed %d frames.\n",frame_cnt-1);
    if(vpx_codec_destroy(&codec))                                             //
        die_codec(&codec, "Failed to destroy codec");                         //

    /* Try to rewrite the file header with the actual frame count */
    if(!fseek(outfile, 0, SEEK_SET))
        write_ivf_file_header(outfile, &cfg, frame_cnt-1);
    fclose(outfile);
    return EXIT_SUCCESS;
}
Esempio n. 29
0
int main(int argc, char **argv) {
    FILE                *infile, *outfile;
    vpx_codec_ctx_t      codec;
    vpx_codec_enc_cfg_t  cfg;
    int                  frame_cnt = 0;
    vpx_image_t          raw;
    vpx_codec_err_t      res;
    long                 width;
    long                 height;
    int                  frame_avail;
    int                  got_data;
    int                  flags = 0;

    /* Open files */
    if(argc!=5)
        die("Usage: %s <width> <height> <infile> <outfile>\n", argv[0]);
    width = strtol(argv[1], NULL, 0);
    height = strtol(argv[2], NULL, 0);
    if(width < 16 || width%2 || height <16 || height%2)
        die("Invalid resolution: %ldx%ld", width, height);
    if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1))
        die("Faile to allocate image", width, height);
    if(!(outfile = fopen(argv[4], "wb")))
        die("Failed to open %s for writing", argv[4]);

    printf("Using %s\n",vpx_codec_iface_name(interface));

    /* Populate encoder configuration */
    res = vpx_codec_enc_config_default(interface, &cfg, 0);
    if(res) {
        printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
        return EXIT_FAILURE;
    }

    /* Update the default configuration with our settings */
    cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate
                            / cfg.g_w / cfg.g_h;
    cfg.g_w = width;
    cfg.g_h = height;

    write_ivf_file_header(outfile, &cfg, 0);


        /* Open input file for this encoding pass */
        if(!(infile = fopen(argv[3], "rb")))
            die("Failed to open %s for reading", argv[3]);

        /* Initialize codec */
        if(vpx_codec_enc_init(&codec, interface, &cfg, 0))
            die_codec(&codec, "Failed to initialize encoder");

        frame_avail = 1;
        got_data = 0;
        while(frame_avail || got_data) {
            vpx_codec_iter_t iter = NULL;
            const vpx_codec_cx_pkt_t *pkt;

            if(frame_cnt + 1 == 22) {                                         //
                vpx_roi_map_t  roi;                                           //
                int            i;                                             //
                                                                              //
                roi.rows = cfg.g_h/16;                                        //
                roi.cols = cfg.g_w/16;                                        //
                                                                              //
                roi.delta_q[0] = 0;                                           //
                roi.delta_q[1] = -2;                                          //
                roi.delta_q[2] = -4;                                          //
                roi.delta_q[3] = -6;                                          //
                                                                              //
                roi.delta_lf[0] = 0;                                          //
                roi.delta_lf[1] = 1;                                          //
                roi.delta_lf[2] = 2;                                          //
                roi.delta_lf[3] = 3;                                          //
                                                                              //
                roi.static_threshold[0] = 1500;                               //
                roi.static_threshold[1] = 1000;                               //
                roi.static_threshold[2] =  500;                               //
                roi.static_threshold[3] =    0;                               //
                                                                              //
                /* generate an ROI map for example */                         //
                roi.roi_map = malloc(roi.rows * roi.cols);                    //
                for(i=0;i<roi.rows*roi.cols;i++)                              //
                    roi.roi_map[i] = i & 3;                                   //
                                                                              //
                if(vpx_codec_control(&codec, VP8E_SET_ROI_MAP, &roi))         //
                    die_codec(&codec, "Failed to set ROI map");               //
                                                                              //
                free(roi.roi_map);                                            //
            } else if(frame_cnt + 1 == 33) {                                  //
                vpx_active_map_t  active;                                     //
                int               i;                                          //
                                                                              //
                active.rows = cfg.g_h/16;                                     //
                active.cols = cfg.g_w/16;                                     //
                                                                              //
                /* generate active map for example */                         //
                active.active_map = malloc(active.rows * active.cols);        //
                for(i=0;i<active.rows*active.cols;i++)                        //
                    active.active_map[i] = i & 1;                             //
                                                                              //
                if(vpx_codec_control(&codec, VP8E_SET_ACTIVEMAP, &active))    //
                    die_codec(&codec, "Failed to set active map");            //
                                                                              //
                free(active.active_map);                                      //
            } else if(frame_cnt + 1 == 44) {                                  //
                vpx_active_map_t  active;                                     //
                                                                              //
                active.rows = cfg.g_h/16;                                     //
                active.cols = cfg.g_w/16;                                     //
                                                                              //
                /* pass in null map to disable active_map*/                   //
                active.active_map = NULL;                                     //
                                                                              //
                if(vpx_codec_control(&codec, VP8E_SET_ACTIVEMAP, &active))    //
                    die_codec(&codec, "Failed to set active map");            //
            }                                                                 //
            frame_avail = read_frame(infile, &raw);
            if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,
                                1, flags, VPX_DL_REALTIME))
                die_codec(&codec, "Failed to encode frame");
            got_data = 0;
            while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
                got_data = 1;
                switch(pkt->kind) {
                case VPX_CODEC_CX_FRAME_PKT:
                    write_ivf_frame_header(outfile, pkt);
                    if(fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
                              outfile));
                    break;
                default:
                    break;
                }
                printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT
                       && (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
                fflush(stdout);
            }
            frame_cnt++;
        }
        printf("\n");
        fclose(infile);

    printf("Processed %d frames.\n",frame_cnt-1);
    if(vpx_codec_destroy(&codec))
        die_codec(&codec, "Failed to destroy codec");

    /* Try to rewrite the file header with the actual frame count */
    if(!fseek(outfile, 0, SEEK_SET))
        write_ivf_file_header(outfile, &cfg, frame_cnt-1);
    fclose(outfile);
    return EXIT_SUCCESS;
}
Esempio n. 30
-2
int main(int argc, char **argv) {
  FILE *infile = NULL;
  vpx_codec_ctx_t codec;
  vpx_codec_enc_cfg_t cfg;
  int frame_count = 0;
  vpx_image_t raw;
  vpx_codec_err_t res;
  VpxVideoInfo info;
  VpxVideoWriter *writer = NULL;
  const VpxInterface *encoder = NULL;
  int update_frame_num = 0;
  const int fps = 30;       // TODO(dkovalev) add command line argument
  const int bitrate = 200;  // kbit/s TODO(dkovalev) add command line argument

  vp8_zero(codec);
  vp8_zero(cfg);
  vp8_zero(info);

  exec_name = argv[0];

  if (argc != 6) die("Invalid number of arguments");

  // TODO(dkovalev): add vp9 support and rename the file accordingly
  encoder = get_vpx_encoder_by_name("vp8");
  if (!encoder) die("Unsupported codec.");

  update_frame_num = atoi(argv[5]);
  if (!update_frame_num) die("Couldn't parse frame number '%s'\n", argv[5]);

  info.codec_fourcc = encoder->fourcc;
  info.frame_width = (int)strtol(argv[1], NULL, 0);
  info.frame_height = (int)strtol(argv[2], NULL, 0);
  info.time_base.numerator = 1;
  info.time_base.denominator = fps;

  if (info.frame_width <= 0 || info.frame_height <= 0 ||
      (info.frame_width % 2) != 0 || (info.frame_height % 2) != 0) {
    die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
  }

  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
                     info.frame_height, 1)) {
    die("Failed to allocate image.");
  }

  printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));

  res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
  if (res) die_codec(&codec, "Failed to get default codec config.");

  cfg.g_w = info.frame_width;
  cfg.g_h = info.frame_height;
  cfg.g_timebase.num = info.time_base.numerator;
  cfg.g_timebase.den = info.time_base.denominator;
  cfg.rc_target_bitrate = bitrate;

  writer = vpx_video_writer_open(argv[4], kContainerIVF, &info);
  if (!writer) die("Failed to open %s for writing.", argv[4]);

  if (!(infile = fopen(argv[3], "rb")))
    die("Failed to open %s for reading.", argv[3]);

  if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
    die_codec(&codec, "Failed to initialize encoder");

  // Encode frames.
  while (vpx_img_read(&raw, infile)) {
    if (frame_count + 1 == update_frame_num) {
      vpx_ref_frame_t ref;
      ref.frame_type = VP8_LAST_FRAME;
      ref.img = raw;
      if (vpx_codec_control(&codec, VP8_SET_REFERENCE, &ref))
        die_codec(&codec, "Failed to set reference frame");
    }

    encode_frame(&codec, &raw, frame_count++, writer);
  }

  // Flush encoder.
  while (encode_frame(&codec, NULL, -1, writer)) {
  }

  printf("\n");
  fclose(infile);
  printf("Processed %d frames.\n", frame_count);

  vpx_img_free(&raw);
  if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");

  vpx_video_writer_close(writer);

  return EXIT_SUCCESS;
}