Пример #1
0
static void *aac_create(obs_data_t settings, obs_encoder_t encoder)
{
	struct aac_encoder *enc;
	int                bitrate = (int)obs_data_getint(settings, "bitrate");
	audio_t            audio   = obs_encoder_audio(encoder);

	if (!bitrate) {
		aac_warn("aac_create", "Invalid bitrate specified");
		return NULL;
	}

	avcodec_register_all();

	enc          = bzalloc(sizeof(struct aac_encoder));
	enc->encoder = encoder;
	enc->aac     = avcodec_find_encoder(AV_CODEC_ID_AAC);
	if (!enc->aac) {
		aac_warn("aac_create", "Couldn't find encoder");
		goto fail;
	}

	blog(LOG_INFO, "Using ffmpeg \"%s\" aac encoder", enc->aac->name);

	enc->context = avcodec_alloc_context3(enc->aac);
	if (!enc->context) {
		aac_warn("aac_create", "Failed to create codec context");
		goto fail;
	}

	enc->context->bit_rate    = bitrate * 1000;
	enc->context->channels    = (int)audio_output_channels(audio);
	enc->context->sample_rate = audio_output_samplerate(audio);
	enc->context->sample_fmt  = enc->aac->sample_fmts ?
		enc->aac->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;

	init_sizes(enc, audio);

	/* enable experimental FFmpeg encoder if the only one available */
	enc->context->strict_std_compliance = -2;

	enc->context->flags = CODEC_FLAG_GLOBAL_HEADER;

	if (initialize_codec(enc))
		return enc;

fail:
	aac_destroy(enc);
	return NULL;
}
Пример #2
0
static void *aac_create(obs_data_t *settings, obs_encoder_t *encoder)
{
	struct aac_encoder *enc;
	int                bitrate = (int)obs_data_get_int(settings, "bitrate");
	audio_t            *audio   = obs_encoder_audio(encoder);

	avcodec_register_all();

	enc          = bzalloc(sizeof(struct aac_encoder));
	enc->encoder = encoder;
	enc->aac     = avcodec_find_encoder(AV_CODEC_ID_AAC);

	blog(LOG_INFO, "---------------------------------");

	if (!enc->aac) {
		warn("Couldn't find encoder");
		goto fail;
	}

	if (!bitrate) {
		warn("Invalid bitrate specified");
		return NULL;
	}

	enc->context = avcodec_alloc_context3(enc->aac);
	if (!enc->context) {
		warn("Failed to create codec context");
		goto fail;
	}

	enc->context->bit_rate    = bitrate * 1000;
	enc->context->channels    = (int)audio_output_get_channels(audio);
	enc->context->sample_rate = audio_output_get_sample_rate(audio);
	enc->context->sample_fmt  = enc->aac->sample_fmts ?
		enc->aac->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;

	/* if using FFmpeg's AAC encoder, at least set a cutoff value
	 * (recommended by konverter) */
	if (strcmp(enc->aac->name, "aac") == 0) {
		int cutoff1 = 4000 + (int)enc->context->bit_rate / 8;
		int cutoff2 = 12000 + (int)enc->context->bit_rate / 8;
		int cutoff3 = enc->context->sample_rate / 2;
		int cutoff;

		cutoff = MIN(cutoff1, cutoff2);
		cutoff = MIN(cutoff, cutoff3);
		enc->context->cutoff = cutoff;
	}

	info("bitrate: %" PRId64 ", channels: %d",
			enc->context->bit_rate / 1000, enc->context->channels);

	init_sizes(enc, audio);

	/* enable experimental FFmpeg encoder if the only one available */
	enc->context->strict_std_compliance = -2;

	enc->context->flags = CODEC_FLAG_GLOBAL_HEADER;

	if (initialize_codec(enc))
		return enc;

fail:
	aac_destroy(enc);
	return NULL;
}
static void *enc_create(obs_data_t *settings, obs_encoder_t *encoder,
		const char *type, const char *alt)
{
	struct enc_encoder *enc;
	int                bitrate = (int)obs_data_get_int(settings, "bitrate");
	audio_t            *audio   = obs_encoder_audio(encoder);

	avcodec_register_all();

	enc          = bzalloc(sizeof(struct enc_encoder));
	enc->encoder = encoder;
	enc->codec   = avcodec_find_encoder_by_name(type);
	enc->type    = type;

	if (!enc->codec && alt) {
		enc->codec = avcodec_find_encoder_by_name(alt);
		enc->type  = alt;
	}

	blog(LOG_INFO, "---------------------------------");

	if (!enc->codec) {
		warn("Couldn't find encoder");
		goto fail;
	}

	if (!bitrate) {
		warn("Invalid bitrate specified");
		return NULL;
	}

	enc->context = avcodec_alloc_context3(enc->codec);
	if (!enc->context) {
		warn("Failed to create codec context");
		goto fail;
	}

	enc->context->bit_rate    = bitrate * 1000;
	enc->context->channels    = (int)audio_output_get_channels(audio);
	enc->context->sample_rate = audio_output_get_sample_rate(audio);
	enc->context->sample_fmt  = enc->codec->sample_fmts ?
		enc->codec->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;

	/* check to make sure sample rate is supported */
	if (enc->codec->supported_samplerates) {
		const int *rate = enc->codec->supported_samplerates;
		int cur_rate = enc->context->sample_rate;
		int closest = 0;

		while (*rate) {
			int dist = abs(cur_rate - *rate);
			int closest_dist = abs(cur_rate - closest);

			if (dist < closest_dist)
				closest = *rate;
			rate++;
		}

		if (closest)
			enc->context->sample_rate = closest;
	}

	/* if using FFmpeg's AAC encoder, at least set a cutoff value
	 * (recommended by konverter) */
	if (strcmp(enc->codec->name, "aac") == 0) {
		int cutoff1 = 4000 + (int)enc->context->bit_rate / 8;
		int cutoff2 = 12000 + (int)enc->context->bit_rate / 8;
		int cutoff3 = enc->context->sample_rate / 2;
		int cutoff;

		cutoff = MIN(cutoff1, cutoff2);
		cutoff = MIN(cutoff, cutoff3);
		enc->context->cutoff = cutoff;
	}

	info("bitrate: %" PRId64 ", channels: %d",
			enc->context->bit_rate / 1000, enc->context->channels);

	init_sizes(enc, audio);

	/* enable experimental FFmpeg encoder if the only one available */
	enc->context->strict_std_compliance = -2;

	enc->context->flags = CODEC_FLAG_GLOBAL_HEADER;

	if (initialize_codec(enc))
		return enc;

fail:
	enc_destroy(enc);
	return NULL;
}
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;
  int frame_avail = 1;
  int got_data = 0;
  int i;
  int frames_in_layer[MAX_LAYERS] = {0};
  clock_t before;
  clock_t after;
  int pts = 0;            /* PTS starts at 0 */
  int frame_duration = 1; /* 1 timebase tick per frame */

  parse_command_line(argc, argv, &cfg);

  // Allocate image buffer
  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, cfg.g_w, cfg.g_h, 32))
    die("Failed to allocate image", cfg.g_w, cfg.g_h);

  set_default_configuration(&cfg);

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

  /* Open output file  */
  for (i = 0; i < number_spatial_layers; i++) {
    char file_name[512];
    snprintf(file_name, sizeof(file_name), "%s_%d.ivf", output_filename, 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(&codec, &cfg);

  // skip initial frames
  for (i = 0; i < number_frames_to_skip; i++) {
    read_frame(infile, &raw);
  }

  before = clock();
  // Encoding frames
  while ((frame_avail || got_data) &&
         frame_cnt <= number_frames_to_code * number_spatial_layers) {
    int flags = 0;
    vpx_codec_iter_t iter = NULL;
    const vpx_codec_cx_pkt_t *pkt;

    int layer = calculate_layer(frame_cnt, number_spatial_layers);
    int is_I_frame_in_layer =
        (((frame_cnt - 1) / number_spatial_layers % key_period) == 0);
    int is_dummy = (frame_cnt == 0);

    if (is_dummy) {  // Dummy frame
      flags = VPX_EFLAG_FORCE_KF;
      frame_avail = read_dummy_frame(&raw);

    } else {  // Regular frame
      // Read a new frame only at the base layer
      if (layer == 0) frame_avail = read_frame(infile, &raw);
      switch_to_layer(layer, cfg.g_w, cfg.g_h, &codec);
      flags = get_flag(is_I_frame_in_layer, layer, INTER_LAYER_PREDICTION_I);
    }

    // Actual Encoding
    if (vpx_codec_encode(&codec, frame_avail ? &raw : NULL, pts, 1, flags,
                         VPX_DL_REALTIME))
      die_codec(&codec, "Failed to encode frame");

    got_data = 0;
    // Process data / Get PSNR statistics
    while ((pkt = vpx_codec_get_cx_data(&codec, &iter))) {
      got_data = 1;
      switch (pkt->kind) {
        case VPX_CODEC_CX_FRAME_PKT:
          for (i = layer; i < number_spatial_layers; i++) {
            write_ivf_frame_header(outfile[i], pkt);
            (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
                         outfile[i]);
            frames_in_layer[i]++;
          }
          break;
        case VPX_CODEC_PSNR_PKT:
          if (frame_cnt != 0)
            printf(
                "Processed Frame %d, layer %d, PSNR(Total/Y/U/V): "
                "%2.3f  %2.3f  %2.3f  %2.3f \n",
                (frame_cnt - 1) / number_spatial_layers + 1, layer,
                pkt->data.psnr.psnr[0], pkt->data.psnr.psnr[1],
                pkt->data.psnr.psnr[2], pkt->data.psnr.psnr[3]);
          break;
        default:
          break;
      }
    }
    frame_cnt++;
    // TODO(ivan): Modify ts later if(!layer)
    pts += frame_duration;
  }
  // end while

  after = clock();
  printf("Processed %d frames in different resolutions in %ld ms.\n",
         frame_cnt - 1, (int)(after - before) / (CLOCKS_PER_SEC / 1000));

  fclose(infile);

  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 < number_spatial_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;
}