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.

331 lines
9.8KB

  1. /*
  2. * JPEG 2000 encoding support via OpenJPEG
  3. * Copyright (c) 2011 Michael Bradshaw <mbradshaw@sorensonmedia.com>
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. /**
  22. * @file
  23. * JPEG 2000 encoder using libopenjpeg
  24. */
  25. #include "libavutil/imgutils.h"
  26. #include "avcodec.h"
  27. #include "libavutil/intreadwrite.h"
  28. #define OPJ_STATIC
  29. #include <openjpeg.h>
  30. typedef struct {
  31. opj_image_t *image;
  32. opj_cparameters_t enc_params;
  33. opj_cinfo_t *compress;
  34. opj_event_mgr_t event_mgr;
  35. } LibOpenJPEGContext;
  36. static void error_callback(const char *msg, void *data)
  37. {
  38. av_log((AVCodecContext*)data, AV_LOG_ERROR, "libopenjpeg: %s\n", msg);
  39. }
  40. static void warning_callback(const char *msg, void *data)
  41. {
  42. av_log((AVCodecContext*)data, AV_LOG_WARNING, "libopenjpeg: %s\n", msg);
  43. }
  44. static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *parameters)
  45. {
  46. opj_image_cmptparm_t *cmptparm;
  47. opj_image_t *img;
  48. int i;
  49. int bpp;
  50. int sub_dx[4];
  51. int sub_dy[4];
  52. int numcomps = 0;
  53. OPJ_COLOR_SPACE color_space = CLRSPC_UNKNOWN;
  54. switch (avctx->pix_fmt) {
  55. case PIX_FMT_GRAY8:
  56. color_space = CLRSPC_GRAY;
  57. numcomps = 1;
  58. bpp = 8;
  59. sub_dx[0] = 1;
  60. sub_dy[0] = 1;
  61. break;
  62. case PIX_FMT_RGB24:
  63. color_space = CLRSPC_SRGB;
  64. numcomps = 3;
  65. bpp = 24;
  66. sub_dx[0] = sub_dx[1] = sub_dx[2] = 1;
  67. sub_dy[0] = sub_dy[1] = sub_dy[2] = 1;
  68. break;
  69. case PIX_FMT_RGBA:
  70. color_space = CLRSPC_SRGB;
  71. numcomps = 4;
  72. bpp = 32;
  73. sub_dx[0] = sub_dx[1] = sub_dx[2] = sub_dx[3] = 1;
  74. sub_dy[0] = sub_dy[1] = sub_dy[2] = sub_dy[3] = 1;
  75. break;
  76. case PIX_FMT_YUV420P:
  77. color_space = CLRSPC_SYCC;
  78. numcomps = 3;
  79. bpp = 12;
  80. sub_dx[0] = 1;
  81. sub_dx[1] = sub_dx[2] = 2;
  82. sub_dy[0] = 1;
  83. sub_dy[1] = sub_dy[2] = 2;
  84. break;
  85. case PIX_FMT_YUV422P:
  86. color_space = CLRSPC_SYCC;
  87. numcomps = 3;
  88. bpp = 16;
  89. sub_dx[0] = 1;
  90. sub_dx[1] = sub_dx[2] = 2;
  91. sub_dy[0] = sub_dy[1] = sub_dy[2] = 1;
  92. break;
  93. case PIX_FMT_YUV440P:
  94. color_space = CLRSPC_SYCC;
  95. numcomps = 3;
  96. bpp = 16;
  97. sub_dx[0] = sub_dx[1] = sub_dx[2] = 1;
  98. sub_dy[0] = 1;
  99. sub_dy[1] = sub_dy[2] = 2;
  100. break;
  101. case PIX_FMT_YUV444P:
  102. color_space = CLRSPC_SYCC;
  103. numcomps = 3;
  104. bpp = 24;
  105. sub_dx[0] = sub_dx[1] = sub_dx[2] = 1;
  106. sub_dy[0] = sub_dy[1] = sub_dy[2] = 1;
  107. break;
  108. default:
  109. av_log(avctx, AV_LOG_ERROR, "The requested pixel format '%s' is not supported\n", av_get_pix_fmt_name(avctx->pix_fmt));
  110. return NULL;
  111. }
  112. cmptparm = av_malloc(numcomps * sizeof(opj_image_cmptparm_t));
  113. if (!cmptparm) {
  114. av_log(avctx, AV_LOG_ERROR, "Not enough memory");
  115. return NULL;
  116. }
  117. memset(cmptparm, 0, numcomps * sizeof(opj_image_cmptparm_t));
  118. for (i = 0; i < numcomps; i++) {
  119. cmptparm[i].prec = 8;
  120. cmptparm[i].bpp = bpp;
  121. cmptparm[i].sgnd = 0;
  122. cmptparm[i].dx = sub_dx[i];
  123. cmptparm[i].dy = sub_dy[i];
  124. cmptparm[i].w = avctx->width / sub_dx[i];
  125. cmptparm[i].h = avctx->height / sub_dy[i];
  126. }
  127. img = opj_image_create(numcomps, cmptparm, color_space);
  128. av_freep(&cmptparm);
  129. return img;
  130. }
  131. static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx)
  132. {
  133. LibOpenJPEGContext *ctx = avctx->priv_data;
  134. opj_set_default_encoder_parameters(&ctx->enc_params);
  135. ctx->enc_params.tcp_numlayers = 1;
  136. ctx->enc_params.tcp_rates[0] = avctx->compression_level > 0 ? avctx->compression_level : 0;
  137. ctx->enc_params.cp_disto_alloc = 1;
  138. ctx->compress = opj_create_compress(CODEC_J2K);
  139. if (!ctx->compress) {
  140. av_log(avctx, AV_LOG_ERROR, "Error creating the compressor\n");
  141. return AVERROR(ENOMEM);
  142. }
  143. avctx->coded_frame = avcodec_alloc_frame();
  144. if (!avctx->coded_frame) {
  145. av_freep(&ctx->compress);
  146. ctx->compress = NULL;
  147. av_log(avctx, AV_LOG_ERROR, "Error allocating coded frame\n");
  148. return AVERROR(ENOMEM);
  149. }
  150. ctx->image = mj2_create_image(avctx, &ctx->enc_params);
  151. if (!ctx->image) {
  152. av_freep(&ctx->compress);
  153. ctx->compress = NULL;
  154. av_freep(&avctx->coded_frame);
  155. avctx->coded_frame = NULL;
  156. av_log(avctx, AV_LOG_ERROR, "Error creating the mj2 image\n");
  157. return AVERROR(EINVAL);
  158. }
  159. memset(&ctx->event_mgr, 0, sizeof(opj_event_mgr_t));
  160. ctx->event_mgr.error_handler = error_callback;
  161. ctx->event_mgr.warning_handler = warning_callback;
  162. ctx->event_mgr.info_handler = NULL;
  163. opj_set_event_mgr((opj_common_ptr)ctx->compress, &ctx->event_mgr, avctx);
  164. return 0;
  165. }
  166. static int libopenjpeg_copy_rgba(AVCodecContext *avctx, AVFrame *frame, opj_image_t *image, int numcomps)
  167. {
  168. int compno;
  169. int x;
  170. int y;
  171. if (numcomps != 1 && numcomps != 3 && numcomps != 4) {
  172. return 0;
  173. }
  174. for (compno = 0; compno < numcomps; ++compno) {
  175. if (image->comps[compno].w > frame->linesize[0] / numcomps) {
  176. return 0;
  177. }
  178. }
  179. for (compno = 0; compno < numcomps; ++compno) {
  180. for (y = 0; y < avctx->height; ++y) {
  181. for (x = 0; x < avctx->width; ++x) {
  182. image->comps[compno].data[y * avctx->width + x] = frame->data[0][y * frame->linesize[0] + x * numcomps + compno];
  183. }
  184. }
  185. }
  186. return 1;
  187. }
  188. static int libopenjpeg_copy_yuv(AVCodecContext *avctx, AVFrame *frame, opj_image_t *image)
  189. {
  190. int compno;
  191. int x;
  192. int y;
  193. int width;
  194. int height;
  195. const int numcomps = 3;
  196. for (compno = 0; compno < numcomps; ++compno) {
  197. if (image->comps[compno].w > frame->linesize[compno]) {
  198. return 0;
  199. }
  200. }
  201. for (compno = 0; compno < numcomps; ++compno) {
  202. width = avctx->width / image->comps[compno].dx;
  203. height = avctx->height / image->comps[compno].dy;
  204. for (y = 0; y < height; ++y) {
  205. for (x = 0; x < width; ++x) {
  206. image->comps[compno].data[y * width + x] = frame->data[compno][y * frame->linesize[compno] + x];
  207. }
  208. }
  209. }
  210. return 1;
  211. }
  212. static int libopenjpeg_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
  213. {
  214. AVFrame *frame = data;
  215. LibOpenJPEGContext *ctx = avctx->priv_data;
  216. opj_cinfo_t *compress = ctx->compress;
  217. opj_image_t *image = ctx->image;
  218. opj_cio_t *stream;
  219. int cpyresult = 0;
  220. int len = 0;
  221. // x0, y0 is the top left corner of the image
  222. // x1, y1 is the width, height of the reference grid
  223. image->x0 = 0;
  224. image->y0 = 0;
  225. image->x1 = (avctx->width - 1) * ctx->enc_params.subsampling_dx + 1;
  226. image->y1 = (avctx->height - 1) * ctx->enc_params.subsampling_dy + 1;
  227. switch (avctx->pix_fmt) {
  228. case PIX_FMT_GRAY8:
  229. cpyresult = libopenjpeg_copy_rgba(avctx, frame, image, 1);
  230. break;
  231. case PIX_FMT_RGB24:
  232. cpyresult = libopenjpeg_copy_rgba(avctx, frame, image, 3);
  233. break;
  234. case PIX_FMT_RGBA:
  235. cpyresult = libopenjpeg_copy_rgba(avctx, frame, image, 4);
  236. break;
  237. case PIX_FMT_YUV420P:
  238. case PIX_FMT_YUV422P:
  239. case PIX_FMT_YUV440P:
  240. case PIX_FMT_YUV444P:
  241. cpyresult = libopenjpeg_copy_yuv(avctx, frame, image);
  242. break;
  243. default:
  244. av_log(avctx, AV_LOG_ERROR, "The frame's pixel format '%s' is not supported\n", av_get_pix_fmt_name(avctx->pix_fmt));
  245. return AVERROR(EINVAL);
  246. break;
  247. }
  248. if (!cpyresult) {
  249. av_log(avctx, AV_LOG_ERROR, "Could not copy the frame data to the internal image buffer\n");
  250. return -1;
  251. }
  252. opj_setup_encoder(compress, &ctx->enc_params, image);
  253. stream = opj_cio_open((opj_common_ptr)compress, NULL, 0);
  254. if (!stream) {
  255. av_log(avctx, AV_LOG_ERROR, "Error creating the cio stream\n");
  256. return AVERROR(ENOMEM);
  257. }
  258. if (!opj_encode(compress, stream, image, NULL)) {
  259. opj_cio_close(stream);
  260. av_log(avctx, AV_LOG_ERROR, "Error during the opj encode\n");
  261. return -1;
  262. }
  263. len = cio_tell(stream);
  264. if (len > buf_size) {
  265. opj_cio_close(stream);
  266. av_log(avctx, AV_LOG_ERROR, "Error with buf_size, not large enough to hold the frame\n");
  267. return -1;
  268. }
  269. memcpy(buf, stream->buffer, len);
  270. opj_cio_close(stream);
  271. return len;
  272. }
  273. static av_cold int libopenjpeg_encode_close(AVCodecContext *avctx)
  274. {
  275. LibOpenJPEGContext *ctx = avctx->priv_data;
  276. opj_destroy_compress(ctx->compress);
  277. opj_image_destroy(ctx->image);
  278. av_freep(&avctx->coded_frame);
  279. return 0 ;
  280. }
  281. AVCodec ff_libopenjpeg_encoder = {
  282. .name = "libopenjpeg",
  283. .type = AVMEDIA_TYPE_VIDEO,
  284. .id = CODEC_ID_JPEG2000,
  285. .priv_data_size = sizeof(LibOpenJPEGContext),
  286. .init = libopenjpeg_encode_init,
  287. .encode = libopenjpeg_encode_frame,
  288. .close = libopenjpeg_encode_close,
  289. .decode = NULL,
  290. .capabilities = 0,
  291. .pix_fmts = (const enum PixelFormat[]){PIX_FMT_GRAY8,PIX_FMT_RGB24,PIX_FMT_RGBA,PIX_FMT_YUV420P,PIX_FMT_YUV422P,PIX_FMT_YUV440P,PIX_FMT_YUV444P},
  292. .long_name = NULL_IF_CONFIG_SMALL("OpenJPEG based JPEG 2000 encoder/decoder"),
  293. } ;