fork of https://bellard.org/bpg/ Better Portable Graphics format including working WASM (WebAssembly) build.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

257 lines
6.7 KiB

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