0
|
1 #ifdef WIN32
|
|
2 #include <windows.h>
|
|
3 #endif
|
|
4 #include <unistd.h>
|
|
5 #include <iostream>
|
|
6 #include "TAppEncTop.h"
|
|
7 #include "TLibCommon/Debug.h"
|
|
8 #include "TLibEncoder/TEncAnalyze.h"
|
|
9
|
|
10 #include "bpgenc.h"
|
|
11
|
|
12 struct HEVCEncoderContext {
|
|
13 HEVCEncodeParams params;
|
|
14 char infilename[1024];
|
|
15 char outfilename[1024];
|
|
16 FILE *yuv_file;
|
|
17 int frame_count;
|
|
18 };
|
|
19
|
|
20 #define ARGV_MAX 256
|
|
21
|
|
22 static void add_opt(int *pargc, char **argv,
|
|
23 const char *str)
|
|
24 {
|
|
25 int argc;
|
|
26 argc = *pargc;
|
|
27 if (argc >= ARGV_MAX)
|
|
28 abort();
|
|
29 argv[argc++] = strdup(str);
|
|
30 *pargc = argc;
|
|
31 }
|
|
32
|
|
33 static HEVCEncoderContext *jctvc_open(const HEVCEncodeParams *params)
|
|
34 {
|
|
35 HEVCEncoderContext *s;
|
|
36 char buf[1024];
|
|
37 static int tmp_idx = 1;
|
|
38
|
|
39 s = (HEVCEncoderContext *)malloc(sizeof(HEVCEncoderContext));
|
|
40 memset(s, 0, sizeof(*s));
|
|
41
|
|
42 s->params = *params;
|
|
43 #ifdef WIN32
|
|
44 if (GetTempPath(sizeof(buf), buf) > sizeof(buf) - 1) {
|
|
45 fprintf(stderr, "Temporary path too long\n");
|
|
46 free(s);
|
|
47 return NULL;
|
|
48 }
|
|
49 #else
|
|
50 strcpy(buf, "/tmp/");
|
|
51 #endif
|
|
52 snprintf(s->infilename, sizeof(s->infilename), "%sout%d-%d.yuv", buf, getpid(), tmp_idx);
|
|
53 snprintf(s->outfilename, sizeof(s->outfilename), "%sout%d-%d.bin", buf, getpid(), tmp_idx);
|
|
54 tmp_idx++;
|
|
55
|
|
56 s->yuv_file = fopen(s->infilename, "wb");
|
|
57 if (!s->yuv_file) {
|
|
58 fprintf(stderr, "Could not open '%s'\n", s->infilename);
|
|
59 free(s);
|
|
60 return NULL;
|
|
61 }
|
|
62 return s;
|
|
63 }
|
|
64
|
|
65 static int jctvc_encode(HEVCEncoderContext *s, Image *img)
|
|
66 {
|
|
67 save_yuv1(img, s->yuv_file);
|
|
68 s->frame_count++;
|
|
69 return 0;
|
|
70 }
|
|
71
|
|
72 /* return the encoded data in *pbuf and the size. Return < 0 if error */
|
|
73 static int jctvc_close(HEVCEncoderContext *s, uint8_t **pbuf)
|
|
74 {
|
|
75 TAppEncTop cTAppEncTop;
|
|
76 int argc;
|
|
77 char *argv[ARGV_MAX + 1];
|
|
78 char buf[1024];
|
|
79 const char *str;
|
|
80 FILE *f;
|
|
81 uint8_t *out_buf;
|
|
82 int out_buf_len, i;
|
|
83
|
|
84 fclose(s->yuv_file);
|
|
85 s->yuv_file = NULL;
|
|
86
|
|
87 m_gcAnalyzeAll.clear();
|
|
88 m_gcAnalyzeI.clear();
|
|
89 m_gcAnalyzeP.clear();
|
|
90 m_gcAnalyzeB.clear();
|
|
91 m_gcAnalyzeAll_in.clear();
|
|
92
|
|
93 cTAppEncTop.create();
|
|
94
|
|
95 argc = 0;
|
|
96 add_opt(&argc, argv, "jctvc"); /* dummy executable name */
|
|
97
|
|
98 snprintf(buf, sizeof(buf),"--InputFile=%s", s->infilename);
|
|
99 add_opt(&argc, argv, buf);
|
|
100 snprintf(buf, sizeof(buf),"--BitstreamFile=%s", s->outfilename);
|
|
101 add_opt(&argc, argv, buf);
|
|
102
|
|
103 snprintf(buf, sizeof(buf),"--SourceWidth=%d", s->params.width);
|
|
104 add_opt(&argc, argv, buf);
|
|
105 snprintf(buf, sizeof(buf),"--SourceHeight=%d", s->params.height);
|
|
106 add_opt(&argc, argv, buf);
|
|
107 snprintf(buf, sizeof(buf),"--InputBitDepth=%d", s->params.bit_depth);
|
|
108 add_opt(&argc, argv, buf);
|
|
109
|
|
110 switch(s->params.chroma_format) {
|
|
111 case BPG_FORMAT_GRAY:
|
|
112 str = "400";
|
|
113 break;
|
|
114 case BPG_FORMAT_420:
|
|
115 str = "420";
|
|
116 break;
|
|
117 case BPG_FORMAT_422:
|
|
118 str = "422";
|
|
119 break;
|
|
120 case BPG_FORMAT_444:
|
|
121 str = "444";
|
|
122 break;
|
|
123 default:
|
|
124 abort();
|
|
125 }
|
|
126 snprintf(buf, sizeof(buf),"--InputChromaFormat=%s", str);
|
|
127 add_opt(&argc, argv, buf);
|
|
128
|
|
129 snprintf(buf, sizeof(buf),"--QP=%d", s->params.qp);
|
|
130 add_opt(&argc, argv, buf);
|
|
131
|
|
132 snprintf(buf, sizeof(buf),"--SEIDecodedPictureHash=%d",
|
|
133 s->params.sei_decoded_picture_hash);
|
|
134 add_opt(&argc, argv, buf);
|
|
135
|
|
136 if (!s->params.verbose)
|
|
137 add_opt(&argc, argv, "--Verbose=0");
|
|
138
|
|
139 /* single frame */
|
|
140 snprintf(buf, sizeof(buf),"--FramesToBeEncoded=%d", s->frame_count);
|
|
141 add_opt(&argc, argv, buf);
|
|
142
|
|
143 /* no padding necessary (it is done before) */
|
|
144 add_opt(&argc, argv, "--ConformanceWindowMode=0");
|
|
145
|
|
146 /* dummy frame rate */
|
|
147 add_opt(&argc, argv, "--FrameRate=25");
|
|
148
|
|
149 /* general config */
|
|
150 add_opt(&argc, argv, "--QuadtreeTULog2MaxSize=5");
|
|
151 if (s->params.compress_level == 9) {
|
|
152 add_opt(&argc, argv, "--QuadtreeTUMaxDepthIntra=4");
|
|
153 add_opt(&argc, argv, "--QuadtreeTUMaxDepthInter=4");
|
|
154 } else {
|
|
155 add_opt(&argc, argv, "--QuadtreeTUMaxDepthIntra=3");
|
|
156 add_opt(&argc, argv, "--QuadtreeTUMaxDepthInter=3");
|
|
157 }
|
|
158
|
|
159 if (s->params.intra_only) {
|
|
160 add_opt(&argc, argv, "--Profile=main_444_16_intra");
|
|
161
|
|
162 add_opt(&argc, argv, "--IntraPeriod=1");
|
|
163 add_opt(&argc, argv, "--GOPSize=1");
|
|
164 } else {
|
|
165 int gop_size;
|
|
166
|
|
167 add_opt(&argc, argv, "--Profile=main_444_16");
|
|
168 add_opt(&argc, argv, "--IntraPeriod=250");
|
|
169 gop_size = 1;
|
|
170 snprintf(buf, sizeof(buf), "--GOPSize=%d", gop_size);
|
|
171 add_opt(&argc, argv, buf);
|
|
172
|
|
173 for(i = 0; i < gop_size; i++) {
|
|
174 snprintf(buf, sizeof(buf), "--Frame%d=P 1 3 0.4624 0 0 0 1 1 -1 0", i + 1);
|
|
175 add_opt(&argc, argv, buf);
|
|
176 }
|
|
177 }
|
|
178 add_opt(&argc, argv, "--TransformSkip=1");
|
|
179 add_opt(&argc, argv, "--TransformSkipFast=1");
|
|
180
|
|
181 /* Note: Format Range extension */
|
|
182 if (s->params.chroma_format == BPG_FORMAT_444) {
|
|
183 add_opt(&argc, argv, "--CrossComponentPrediction=1");
|
|
184 }
|
|
185
|
|
186 if (s->params.lossless) {
|
|
187 add_opt(&argc, argv, "--CostMode=lossless");
|
|
188 add_opt(&argc, argv, "--SAO=0");
|
|
189 add_opt(&argc, argv, "--LoopFilterDisable");
|
|
190 add_opt(&argc, argv, "--TransquantBypassEnableFlag");
|
|
191 add_opt(&argc, argv, "--CUTransquantBypassFlagForce");
|
|
192 add_opt(&argc, argv, "--ImplicitResidualDPCM");
|
|
193 add_opt(&argc, argv, "--GolombRiceParameterAdaptation");
|
|
194 add_opt(&argc, argv, "--HadamardME=0");
|
|
195 }
|
|
196
|
|
197 #if 0
|
|
198 /* TEST with several slices */
|
|
199 add_opt(&argc, argv, "--SliceMode=2");
|
|
200 add_opt(&argc, argv, "--SliceArgument=5");
|
|
201 #endif
|
|
202
|
|
203 /* trailing NULL */
|
|
204 argv[argc] = NULL;
|
|
205
|
|
206 if (s->params.verbose >= 2) {
|
|
207 int i;
|
|
208 printf("Encode options:");
|
|
209 for(i = 0; i < argc; i++) {
|
|
210 printf(" %s", argv[i]);
|
|
211 }
|
|
212 printf("\n");
|
|
213 }
|
|
214
|
|
215 if(!cTAppEncTop.parseCfg( argc, argv )) {
|
|
216 fprintf(stderr, "Error while parsing options\n");
|
|
217 cTAppEncTop.destroy();
|
|
218 return -1;
|
|
219 }
|
|
220
|
|
221 cTAppEncTop.encode();
|
|
222
|
|
223 cTAppEncTop.destroy();
|
|
224
|
|
225 for(i = 0; i < argc; i++)
|
|
226 free(argv[i]);
|
|
227 unlink(s->infilename);
|
|
228
|
|
229 /* read output bitstream */
|
|
230 f = fopen(s->outfilename, "rb");
|
|
231 if (!f) {
|
|
232 fprintf(stderr, "Could not open '%s'\n", s->outfilename);
|
|
233 return -1;
|
|
234 }
|
|
235
|
|
236 fseek(f, 0, SEEK_END);
|
|
237 out_buf_len = ftell(f);
|
|
238 fseek(f, 0, SEEK_SET);
|
|
239 out_buf = (uint8_t *)malloc(out_buf_len);
|
|
240 if (fread(out_buf, 1, out_buf_len, f) != out_buf_len) {
|
|
241 fprintf(stderr, "read error\n");
|
|
242 fclose(f);
|
|
243 free(out_buf);
|
|
244 return -1;
|
|
245 }
|
|
246 fclose(f);
|
|
247 unlink(s->outfilename);
|
|
248 *pbuf = out_buf;
|
|
249 free(s);
|
|
250 return out_buf_len;
|
|
251 }
|
|
252
|
|
253 HEVCEncoder jctvc_encoder = {
|
|
254 .open = jctvc_open,
|
|
255 .encode = jctvc_encode,
|
|
256 .close = jctvc_close,
|
|
257 };
|