1 /*
2 * Copyright (c) 2023 The WebM project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <stdlib.h>
12
13 #include "vpx/vpx_codec.h"
14 #include "vpx/vpx_tpl.h"
15 #include "vpx_mem/vpx_mem.h"
16
17 #define CHECK_FPRINTF_ERROR(expr) \
18 do { \
19 if (expr < 0) { \
20 return VPX_CODEC_ERROR; \
21 } \
22 } while (0)
23
24 #define CHECK_FSCANF_ERROR(expr, expected_value) \
25 do { \
26 if (expr != expected_value) { \
27 return VPX_CODEC_ERROR; \
28 } \
29 } while (0)
30
vpx_write_tpl_gop_stats(FILE * tpl_file,const VpxTplGopStats * tpl_gop_stats)31 vpx_codec_err_t vpx_write_tpl_gop_stats(FILE *tpl_file,
32 const VpxTplGopStats *tpl_gop_stats) {
33 int i;
34 if (tpl_file == NULL || tpl_gop_stats == NULL) return VPX_CODEC_INVALID_PARAM;
35 CHECK_FPRINTF_ERROR(fprintf(tpl_file, "%d\n", tpl_gop_stats->size));
36
37 for (i = 0; i < tpl_gop_stats->size; i++) {
38 VpxTplFrameStats frame_stats = tpl_gop_stats->frame_stats_list[i];
39 const int num_blocks = frame_stats.num_blocks;
40 int block;
41 CHECK_FPRINTF_ERROR(fprintf(tpl_file, "%d %d %d\n", frame_stats.frame_width,
42 frame_stats.frame_height, num_blocks));
43 for (block = 0; block < num_blocks; block++) {
44 VpxTplBlockStats block_stats = frame_stats.block_stats_list[block];
45 CHECK_FPRINTF_ERROR(
46 fprintf(tpl_file,
47 "%" PRId64 " %" PRId64 " %" PRId16 " %" PRId16 " %" PRId64
48 " %" PRId64 " %d\n",
49 block_stats.inter_cost, block_stats.intra_cost,
50 block_stats.mv_c, block_stats.mv_r, block_stats.recrf_dist,
51 block_stats.recrf_rate, block_stats.ref_frame_index));
52 }
53 }
54
55 return VPX_CODEC_OK;
56 }
57
vpx_read_tpl_gop_stats(FILE * tpl_file,VpxTplGopStats * tpl_gop_stats)58 vpx_codec_err_t vpx_read_tpl_gop_stats(FILE *tpl_file,
59 VpxTplGopStats *tpl_gop_stats) {
60 int i, frame_list_size;
61 if (tpl_file == NULL || tpl_gop_stats == NULL) return VPX_CODEC_INVALID_PARAM;
62 CHECK_FSCANF_ERROR(fscanf(tpl_file, "%d\n", &frame_list_size), 1);
63 tpl_gop_stats->size = frame_list_size;
64 tpl_gop_stats->frame_stats_list = (VpxTplFrameStats *)vpx_calloc(
65 frame_list_size, sizeof(tpl_gop_stats->frame_stats_list[0]));
66 if (tpl_gop_stats->frame_stats_list == NULL) {
67 return VPX_CODEC_MEM_ERROR;
68 }
69 for (i = 0; i < frame_list_size; i++) {
70 VpxTplFrameStats *frame_stats = &tpl_gop_stats->frame_stats_list[i];
71 int num_blocks, width, height, block;
72 CHECK_FSCANF_ERROR(
73 fscanf(tpl_file, "%d %d %d\n", &width, &height, &num_blocks), 3);
74 frame_stats->num_blocks = num_blocks;
75 frame_stats->frame_width = width;
76 frame_stats->frame_height = height;
77 frame_stats->block_stats_list = (VpxTplBlockStats *)vpx_calloc(
78 num_blocks, sizeof(frame_stats->block_stats_list[0]));
79 if (frame_stats->block_stats_list == NULL) {
80 vpx_free_tpl_gop_stats(tpl_gop_stats);
81 return VPX_CODEC_MEM_ERROR;
82 }
83 for (block = 0; block < num_blocks; block++) {
84 VpxTplBlockStats *block_stats = &frame_stats->block_stats_list[block];
85 CHECK_FSCANF_ERROR(
86 fscanf(tpl_file,
87 "%" SCNd64 " %" SCNd64 " %" SCNd16 " %" SCNd16 " %" SCNd64
88 " %" SCNd64 " %d\n",
89 &block_stats->inter_cost, &block_stats->intra_cost,
90 &block_stats->mv_c, &block_stats->mv_r,
91 &block_stats->recrf_dist, &block_stats->recrf_rate,
92 &block_stats->ref_frame_index),
93 7);
94 }
95 }
96
97 return VPX_CODEC_OK;
98 }
99
vpx_free_tpl_gop_stats(VpxTplGopStats * tpl_gop_stats)100 void vpx_free_tpl_gop_stats(VpxTplGopStats *tpl_gop_stats) {
101 int frame;
102 if (tpl_gop_stats == NULL) return;
103 for (frame = 0; frame < tpl_gop_stats->size; frame++) {
104 vpx_free(tpl_gop_stats->frame_stats_list[frame].block_stats_list);
105 }
106 vpx_free(tpl_gop_stats->frame_stats_list);
107 }
108