Example #1
0
// dump accumulated statistics and reset accumulated values
const char *vpx_svc_dump_statistics(SvcContext *svc_ctx) {
  int number_of_frames, number_of_keyframes, encode_frame_count;
  int i;
  uint32_t bytes_total = 0;
  SvcInternal *const si = get_svc_internal(svc_ctx);
  if (svc_ctx == NULL || si == NULL) return NULL;

  svc_log_reset(svc_ctx);

  encode_frame_count = si->encode_frame_count;
  if (si->encode_frame_count <= 0) return vpx_svc_get_message(svc_ctx);

  svc_log(svc_ctx, SVC_LOG_INFO, "\n");
  number_of_keyframes = encode_frame_count / si->kf_dist + 1;
  for (i = 0; i < si->layers; ++i) {
    number_of_frames = encode_frame_count;

    if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
        (i == 1 || i == 3)) {
      number_of_frames -= number_of_keyframes;
    }
    svc_log(svc_ctx, SVC_LOG_INFO, "Layer %d PSNR=[%2.3f], Bytes=[%u]\n", i,
            (double)si->psnr_in_layer[i] / number_of_frames,
            si->bytes_in_layer[i]);
    bytes_total += si->bytes_in_layer[i];
    si->psnr_in_layer[i] = 0;
    si->bytes_in_layer[i] = 0;
  }

  // only display statistics once
  si->encode_frame_count = 0;

  svc_log(svc_ctx, SVC_LOG_INFO, "Total Bytes=[%u]\n", bytes_total);
  return vpx_svc_get_message(svc_ctx);
}
// dump accumulated statistics and reset accumulated values
const char *vpx_svc_dump_statistics(SvcContext *svc_ctx) {
  int number_of_frames;
  int i, j;
  uint32_t bytes_total = 0;
  double scale[COMPONENTS];
  double psnr[COMPONENTS];
  double mse[COMPONENTS];
  double y_scale;

  SvcInternal *const si = get_svc_internal(svc_ctx);
  if (svc_ctx == NULL || si == NULL) return NULL;

  svc_log_reset(svc_ctx);

  number_of_frames = si->psnr_pkt_received;
  if (number_of_frames <= 0) return vpx_svc_get_message(svc_ctx);

  svc_log(svc_ctx, SVC_LOG_INFO, "\n");
  for (i = 0; i < svc_ctx->spatial_layers; ++i) {

    svc_log(svc_ctx, SVC_LOG_INFO,
            "Layer %d Average PSNR=[%2.3f, %2.3f, %2.3f, %2.3f], Bytes=[%u]\n",
            i, (double)si->psnr_sum[i][0] / number_of_frames,
            (double)si->psnr_sum[i][1] / number_of_frames,
            (double)si->psnr_sum[i][2] / number_of_frames,
            (double)si->psnr_sum[i][3] / number_of_frames, si->bytes_sum[i]);
    // the following psnr calculation is deduced from ffmpeg.c#print_report
    y_scale = si->width * si->height * 255.0 * 255.0 * number_of_frames;
    scale[1] = y_scale;
    scale[2] = scale[3] = y_scale / 4;  // U or V
    scale[0] = y_scale * 1.5;           // total

    for (j = 0; j < COMPONENTS; j++) {
      psnr[j] = calc_psnr(si->sse_sum[i][j] / scale[j]);
      mse[j] = si->sse_sum[i][j] * 255.0 * 255.0 / scale[j];
    }
    svc_log(svc_ctx, SVC_LOG_INFO,
            "Layer %d Overall PSNR=[%2.3f, %2.3f, %2.3f, %2.3f]\n", i, psnr[0],
            psnr[1], psnr[2], psnr[3]);
    svc_log(svc_ctx, SVC_LOG_INFO,
            "Layer %d Overall MSE=[%2.3f, %2.3f, %2.3f, %2.3f]\n", i, mse[0],
            mse[1], mse[2], mse[3]);

    bytes_total += si->bytes_sum[i];
    // clear sums for next time
    si->bytes_sum[i] = 0;
    for (j = 0; j < COMPONENTS; ++j) {
      si->psnr_sum[i][j] = 0;
      si->sse_sum[i][j] = 0;
    }
  }

  // only display statistics once
  si->psnr_pkt_received = 0;

  svc_log(svc_ctx, SVC_LOG_INFO, "Total Bytes=[%u]\n", bytes_total);
  return vpx_svc_get_message(svc_ctx);
}
/**
 * Encode a frame into multiple layers
 * Create a superframe containing the individual layers
 */
vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
                               struct vpx_image *rawimg, vpx_codec_pts_t pts,
                               int64_t duration, int deadline) {
  vpx_codec_err_t res;
  vpx_codec_iter_t iter;
  const vpx_codec_cx_pkt_t *cx_pkt;
  SvcInternal_t *const si = get_svc_internal(svc_ctx);
  if (svc_ctx == NULL || codec_ctx == NULL || si == NULL) {
    return VPX_CODEC_INVALID_PARAM;
  }

  svc_log_reset(svc_ctx);

  res =
      vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration, 0, deadline);
  if (res != VPX_CODEC_OK) {
    return res;
  }
  // save compressed data
  iter = NULL;
  while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) {
    switch (cx_pkt->kind) {
#if CONFIG_SPATIAL_SVC && defined(VPX_TEST_SPATIAL_SVC)
      case VPX_CODEC_SPATIAL_SVC_LAYER_PSNR: {
        int i;
        for (i = 0; i < svc_ctx->spatial_layers; ++i) {
          int j;
          svc_log(svc_ctx, SVC_LOG_DEBUG,
                  "SVC frame: %d, layer: %d, PSNR(Total/Y/U/V): "
                  "%2.3f  %2.3f  %2.3f  %2.3f \n",
                  si->psnr_pkt_received, i, cx_pkt->data.layer_psnr[i].psnr[0],
                  cx_pkt->data.layer_psnr[i].psnr[1],
                  cx_pkt->data.layer_psnr[i].psnr[2],
                  cx_pkt->data.layer_psnr[i].psnr[3]);
          svc_log(svc_ctx, SVC_LOG_DEBUG,
                  "SVC frame: %d, layer: %d, SSE(Total/Y/U/V): "
                  "%2.3f  %2.3f  %2.3f  %2.3f \n",
                  si->psnr_pkt_received, i, cx_pkt->data.layer_psnr[i].sse[0],
                  cx_pkt->data.layer_psnr[i].sse[1],
                  cx_pkt->data.layer_psnr[i].sse[2],
                  cx_pkt->data.layer_psnr[i].sse[3]);

          for (j = 0; j < COMPONENTS; ++j) {
            si->psnr_sum[i][j] += cx_pkt->data.layer_psnr[i].psnr[j];
            si->sse_sum[i][j] += cx_pkt->data.layer_psnr[i].sse[j];
          }
        }
        ++si->psnr_pkt_received;
        break;
      }
      case VPX_CODEC_SPATIAL_SVC_LAYER_SIZES: {
        int i;
        for (i = 0; i < svc_ctx->spatial_layers; ++i)
          si->bytes_sum[i] += cx_pkt->data.layer_sizes[i];
        break;
      }
#endif
      case VPX_CODEC_PSNR_PKT: {
#if CONFIG_SPATIAL_SVC && defined(VPX_TEST_SPATIAL_SVC)
        int j;
        svc_log(svc_ctx, SVC_LOG_DEBUG,
                "frame: %d, layer: %d, PSNR(Total/Y/U/V): "
                "%2.3f  %2.3f  %2.3f  %2.3f \n",
                si->psnr_pkt_received, 0, cx_pkt->data.layer_psnr[0].psnr[0],
                cx_pkt->data.layer_psnr[0].psnr[1],
                cx_pkt->data.layer_psnr[0].psnr[2],
                cx_pkt->data.layer_psnr[0].psnr[3]);
        for (j = 0; j < COMPONENTS; ++j) {
          si->psnr_sum[0][j] += cx_pkt->data.layer_psnr[0].psnr[j];
          si->sse_sum[0][j] += cx_pkt->data.layer_psnr[0].sse[j];
        }
#endif
      }
        ++si->psnr_pkt_received;
        break;
      default: { break; }
    }
  }

  return VPX_CODEC_OK;
}
Example #4
0
/**
 * Encode a frame into multiple layers
 * Create a superframe containing the individual layers
 */
vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
                               struct vpx_image *rawimg, vpx_codec_pts_t pts,
                               int64_t duration, int deadline) {
  vpx_codec_err_t res;
  vpx_codec_iter_t iter;
  const vpx_codec_cx_pkt_t *cx_pkt;
  struct LayerData *cx_layer_list = NULL;
  struct LayerData *layer_data;
  struct Superframe superframe;
  SvcInternal *const si = get_svc_internal(svc_ctx);
  if (svc_ctx == NULL || codec_ctx == NULL || rawimg == NULL || si == NULL) {
    return VPX_CODEC_INVALID_PARAM;
  }

  memset(&superframe, 0, sizeof(superframe));
  svc_log_reset(svc_ctx);

  si->layers = svc_ctx->spatial_layers;
  if (si->frame_within_gop >= si->kf_dist ||
      si->encode_frame_count == 0) {
    si->frame_within_gop = 0;
  }
  si->is_keyframe = (si->frame_within_gop == 0);
  si->frame_size = 0;

  svc_log(svc_ctx, SVC_LOG_DEBUG,
          "vpx_svc_encode  layers: %d, frame_count: %d, frame_within_gop: %d\n",
          si->layers, si->encode_frame_count, si->frame_within_gop);

  // encode each layer
  for (si->layer = 0; si->layer < si->layers; ++si->layer) {
    if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
        si->is_keyframe && (si->layer == 1 || si->layer == 3)) {
      svc_log(svc_ctx, SVC_LOG_DEBUG, "Skip encoding layer %d\n", si->layer);
      continue;
    }
    calculate_enc_frame_flags(svc_ctx);

    set_svc_parameters(svc_ctx, codec_ctx);

    res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration,
                           si->enc_frame_flags, deadline);
    if (res != VPX_CODEC_OK) {
      return res;
    }
    // save compressed data
    iter = NULL;
    while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) {
      switch (cx_pkt->kind) {
        case VPX_CODEC_CX_FRAME_PKT: {
          const uint32_t frame_pkt_size = (uint32_t)(cx_pkt->data.frame.sz);
          si->bytes_in_layer[si->layer] += frame_pkt_size;
          svc_log(svc_ctx, SVC_LOG_DEBUG,
                  "SVC frame: %d, layer: %d, size: %u\n",
                  si->encode_frame_count, si->layer, frame_pkt_size);
          layer_data =
              ld_create(cx_pkt->data.frame.buf, (size_t)frame_pkt_size);
          if (layer_data == NULL) {
            svc_log(svc_ctx, SVC_LOG_ERROR, "Error allocating LayerData\n");
            return 0;
          }
          ld_list_add(&cx_layer_list, layer_data);

          // save layer size in superframe index
          superframe.sizes[superframe.count++] = frame_pkt_size;
          superframe.magnitude |= frame_pkt_size;
          break;
        }
        case VPX_CODEC_PSNR_PKT: {
          svc_log(svc_ctx, SVC_LOG_DEBUG,
                  "SVC frame: %d, layer: %d, PSNR(Total/Y/U/V): "
                  "%2.3f  %2.3f  %2.3f  %2.3f \n",
                  si->encode_frame_count, si->layer,
                  cx_pkt->data.psnr.psnr[0], cx_pkt->data.psnr.psnr[1],
                  cx_pkt->data.psnr.psnr[2], cx_pkt->data.psnr.psnr[3]);
          si->psnr_in_layer[si->layer] += cx_pkt->data.psnr.psnr[0];
          break;
        }
        default: {
          break;
        }
      }
    }
  }
  // add superframe index to layer data list
  sf_create_index(&superframe);
  layer_data = ld_create(superframe.buffer, superframe.index_size);
  ld_list_add(&cx_layer_list, layer_data);

  // get accumulated size of layer data
  si->frame_size = ld_list_get_buffer_size(cx_layer_list);
  if (si->frame_size == 0) return VPX_CODEC_ERROR;

  // all layers encoded, create single buffer with concatenated layers
  if (si->frame_size > si->buffer_size) {
    free(si->buffer);
    si->buffer = malloc(si->frame_size);
    if (si->buffer == NULL) {
      ld_list_free(cx_layer_list);
      return VPX_CODEC_MEM_ERROR;
    }
    si->buffer_size = si->frame_size;
  }
  // copy layer data into packet
  ld_list_copy_to_buffer(cx_layer_list, si->buffer);

  ld_list_free(cx_layer_list);

  svc_log(svc_ctx, SVC_LOG_DEBUG, "SVC frame: %d, kf: %d, size: %d, pts: %d\n",
          si->encode_frame_count, si->is_keyframe, (int)si->frame_size,
          (int)pts);
  ++si->frame_within_gop;
  ++si->encode_frame_count;

  return VPX_CODEC_OK;
}