예제 #1
0
파일: vpxlib.c 프로젝트: svn2github/Xpra
int decompress_image(struct vpx_context *ctx, const uint8_t *in, int size, uint8_t *out[3], int outstride[3])
{
	vpx_image_t *img;
	int frame_sz = size;
	vpx_codec_iter_t iter = NULL;
	const uint8_t *frame = in;
	int i = 0;

	if (vpx_codec_decode(&ctx->codec, frame, frame_sz, NULL, 0)) {
		codec_error(&ctx->codec, "vpx_codec_decode");
		return -1;
	}
	img = vpx_codec_get_frame(&ctx->codec, &iter);
	if (img == NULL) {
		codec_error(&ctx->codec, "vpx_codec_get_frame");
		return -1;
	}

	for (i = 0; i < 3; i++) {
		out[i] = img->planes[i];
		outstride[i] = img->stride[i];
	}

    ctx->pixfmt = img->fmt;
	return 0;
}
예제 #2
0
bool WebmExporter::add_frame(const vpx_image* data)
{
  auto result =
      vpx_codec_encode(&_codec, data, _frame_index++, 1, 0,
                       _settings.quality <= 1 ? VPX_DL_BEST_QUALITY : VPX_DL_GOOD_QUALITY);
  if (result != VPX_CODEC_OK) {
    codec_error("couldn't encode frame");
    return false;
  }

  vpx_codec_iter_t iter = nullptr;
  const vpx_codec_cx_pkt_t* packet = nullptr;
  bool found_packet = false;
  while (packet = vpx_codec_get_cx_data(&_codec, &iter)) {
    found_packet = true;
    if (packet->kind != VPX_CODEC_CX_FRAME_PKT) {
      continue;
    }
    auto timestamp_ns = 1000000000 * packet->data.frame.pts / _settings.fps;
    bool result =
        _segment.AddFrame((uint8_t*) packet->data.frame.buf, packet->data.frame.sz, _video_track,
                          timestamp_ns, packet->data.frame.flags & VPX_FRAME_IS_KEY);
    if (!result) {
      std::cerr << "couldn't add frame" << std::endl;
      return false;
    }
  }

  return found_packet;
};
예제 #3
0
WebmExporter::~WebmExporter()
{
  if (_img) {
    vpx_img_free(_img);
  }
  // Flush encoder.
  while (add_frame(nullptr))
    ;

  if (vpx_codec_destroy(&_codec)) {
    codec_error("failed to destroy codec");
    return;
  }
  if (!_segment.Finalize()) {
    std::cerr << "couldn't finalise muxer segment" << std::endl;
    return;
  }
  _writer.Close();
}
예제 #4
0
파일: vpxlib.c 프로젝트: svn2github/Xpra
struct vpx_context *init_decoder(int width, int height, const char *colorspace)
{
	int flags = 0;
	int err = 0;
	vpx_codec_iface_t *codec_iface = NULL;
	struct vpx_context *ctx = malloc(sizeof(struct vpx_context));
	if (ctx == NULL)
		return NULL;
	codec_iface = vpx_codec_vp8_dx();
	memset(ctx, 0, sizeof(struct vpx_context));
	err = vpx_codec_dec_init(&ctx->codec, codec_iface, NULL, flags);
	if (err) {
		codec_error(&ctx->codec, "vpx_codec_dec_init");
		printf("vpx_codec_dec_init(..) failed with error %d\n", err);
		free(ctx);
		return NULL;
	}
	ctx->width = width;
	ctx->height = height;
	return ctx;
}
예제 #5
0
파일: vpxlib.c 프로젝트: svn2github/Xpra
int compress_image(struct vpx_context *ctx, uint8_t *input[3], int input_stride[3], uint8_t **out, int *outsz)
{
	struct vpx_image image;
	const vpx_codec_cx_pkt_t *pkt;
	vpx_codec_iter_t iter = NULL;
	int frame_cnt = 0;
	int flags = 0;
	int i = 0;

	/* Encoding */
	memset(&image, 0, sizeof(struct vpx_image));
	image.w = ctx->width;
	image.h = ctx->height;
	image.fmt = ctx->pixfmt;
	image.planes[0] = input[0];
	image.planes[1] = input[1];
	image.planes[2] = input[2];
	image.stride[0] = input_stride[0];
	image.stride[1] = input_stride[1];
	image.stride[2] = input_stride[2];
	image.d_w = ctx->width;
	image.d_h = ctx->height;
	image.x_chroma_shift = 0;
	image.y_chroma_shift = 0;
	image.bps = 8;
	i = vpx_codec_encode(&ctx->codec, &image, frame_cnt, 1, flags, VPX_DL_REALTIME);
	if (i) {
		codec_error(&ctx->codec, "vpx_codec_encode");
		return i;
	}
	pkt = vpx_codec_get_cx_data(&ctx->codec, &iter);
	if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) {
		return 1;
	}
	*out = pkt->data.frame.buf;
	*outsz = pkt->data.frame.sz;
	return 0;
}
예제 #6
0
파일: vpxlib.c 프로젝트: svn2github/Xpra
struct vpx_context *init_encoder(int width, int height, const char *colorspace)
{
	vpx_codec_enc_cfg_t cfg;
	vpx_img_fmt_t vpx_colorspace;
	struct vpx_context *ctx;
	vpx_codec_iface_t *codec_iface;

	vpx_colorspace = get_vpx_colorspace(colorspace);
	if (vpx_colorspace<0)
		return NULL;

	codec_iface = vpx_codec_vp8_cx();
	if (vpx_codec_enc_config_default(codec_iface, &cfg, 0))
		return NULL;

	cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate / cfg.g_w / cfg.g_h;
	cfg.g_w = width;
	cfg.g_h = height;
	cfg.g_error_resilient = 0;
	cfg.g_lag_in_frames = 0;
	cfg.rc_dropframe_thresh = 0;
	//cfg.rc_resize_allowed = 1;
	ctx = malloc(sizeof(struct vpx_context));
	if (ctx == NULL)
		return NULL;
	memset(ctx, 0, sizeof(struct vpx_context));
	if (vpx_codec_enc_init(&ctx->codec, codec_iface, &cfg, 0)) {
		codec_error(&ctx->codec, "vpx_codec_enc_init");
		free(ctx);
		return NULL;
	}
	ctx->width = width;
	ctx->height = height;
	ctx->pixfmt = vpx_colorspace;
	return ctx;
}
예제 #7
0
WebmExporter::WebmExporter(const exporter_settings& settings)
: _success{false}, _settings(settings), _video_track{0}, _img{nullptr}, _frame_index{0}
{
  if (!_writer.Open(settings.path.c_str())) {
    std::cerr << "couldn't open " << settings.path << " for writing" << std::endl;
    return;
  }

  if (!_segment.Init(&_writer)) {
    std::cerr << "couldn't initialise muxer segment" << std::endl;
    return;
  }
  _segment.set_mode(mkvmuxer::Segment::kFile);
  _segment.OutputCues(true);
  _segment.GetSegmentInfo()->set_writing_app("trance");

  _video_track = _segment.AddVideoTrack(settings.width, settings.height, 0);
  if (!_video_track) {
    std::cerr << "couldn't add video track" << std::endl;
    return;
  }

  auto video = (mkvmuxer::VideoTrack*) _segment.GetTrackByNumber(_video_track);
  if (!video) {
    std::cerr << "couldn't get video track" << std::endl;
    return;
  }
  video->set_frame_rate(settings.fps);
  _segment.GetCues()->set_output_block_number(true);
  _segment.CuesTrack(_video_track);

  // See http://www.webmproject.org/docs/encoder-parameters.
  vpx_codec_enc_cfg_t cfg;
  if (vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &cfg, 0)) {
    std::cerr << "couldn't get default codec config" << std::endl;
    return;
  }
  auto area = _settings.width * _settings.height;
  auto bitrate = (1 + 2 * (4 - _settings.quality)) * area / 1024;

  cfg.g_w = _settings.width;
  cfg.g_h = _settings.height;
  cfg.g_timebase.num = 1;
  cfg.g_timebase.den = _settings.fps;
  cfg.g_lag_in_frames = 24;
  cfg.g_threads = settings.threads;
  cfg.kf_min_dist = 0;
  cfg.kf_max_dist = 256;
  cfg.rc_target_bitrate = bitrate;

  if (vpx_codec_enc_init(&_codec, vpx_codec_vp8_cx(), &cfg, 0)) {
    codec_error("couldn't initialise encoder");
    return;
  }

  _img = vpx_img_alloc(nullptr, VPX_IMG_FMT_I420, _settings.width, _settings.height, 16);
  if (!_img) {
    std::cerr << "couldn't allocate image for encoding" << std::endl;
    return;
  }
  _success = true;
}