FFmpeg
libsvtjpegxsdec.c
Go to the documentation of this file.
1 /*
2  * Copyright(c) 2024 Intel Corporation
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /*
22 * Copyright(c) 2024 Intel Corporation
23 * SPDX - License - Identifier: BSD - 2 - Clause - Patent
24 */
25 
26 #include <SvtJpegxsDec.h>
27 
28 #include "libavutil/mem.h"
29 #include "libavutil/common.h"
30 #include "libavutil/cpu.h"
31 #include "libavutil/imgutils.h"
32 #include "libavutil/avassert.h"
33 
34 #include "avcodec.h"
35 #include "codec_internal.h"
36 #include "decode.h"
37 #include "profiles.h"
38 
39 typedef struct SvtJpegXsDecodeContext {
40  svt_jpeg_xs_image_config_t config;
41  svt_jpeg_xs_decoder_api_t decoder;
42  svt_jpeg_xs_frame_t input;
43  svt_jpeg_xs_frame_t output;
45 
48 
49 static int set_pix_fmt(void *logctx, const svt_jpeg_xs_image_config_t *config)
50 {
51  int ret = AVERROR_BUG;
52 
53  switch (config->format) {
54  case COLOUR_FORMAT_PLANAR_YUV420:
55  if (config->bit_depth == 8)
56  return AV_PIX_FMT_YUV420P;
57  else if (config->bit_depth == 10)
59  else if (config->bit_depth == 12)
61  else
63  break;
64  case COLOUR_FORMAT_PLANAR_YUV422:
65  if (config->bit_depth == 8)
66  return AV_PIX_FMT_YUV422P;
67  else if (config->bit_depth == 10)
69  else if (config->bit_depth == 12)
71  else
73  break;
74  case COLOUR_FORMAT_PLANAR_YUV444_OR_RGB:
75  if (config->bit_depth == 8)
76  return AV_PIX_FMT_YUV444P;
77  else if (config->bit_depth == 10)
79  else if (config->bit_depth == 12)
81  else
83  break;
84  default:
85  av_log(logctx, AV_LOG_ERROR, "Unsupported pixel format.\n");
87  break;
88  }
89 
90  return ret;
91 }
92 
93 static int svt_jpegxs_dec_decode(AVCodecContext* avctx, AVFrame* picture, int* got_frame, AVPacket* avpkt)
94 {
95  SvtJpegXsDecodeContext* svt_dec = avctx->priv_data;
96  SvtJxsErrorType_t err = SvtJxsErrorNone;
97  uint32_t frame_size;
98  int ret;
99 
100  err = svt_jpeg_xs_decoder_get_single_frame_size_with_proxy(
101  avpkt->data, avpkt->size, &svt_dec->config, &frame_size, 1 /*quick search*/, svt_dec->decoder.proxy_mode);
102  if (err) {
103  av_log(avctx, AV_LOG_ERROR, "svt_jpeg_xs_decoder_get_single_frame_size_with_proxy failed, err=%d\n", err);
104  return AVERROR_EXTERNAL;
105  }
106  if (avpkt->size < frame_size) {
107  av_log(avctx, AV_LOG_ERROR, "Not enough data in a packet.\n");
108  return AVERROR(EINVAL);
109  }
110  if (avpkt->size > frame_size) {
111  av_log(avctx, AV_LOG_ERROR, "Single packet have data for more than one frame.\n");
112  return AVERROR(EINVAL);
113  }
114 
115  ret = set_pix_fmt(avctx, &svt_dec->config);
116  if (ret < 0)
117  return ret;
118 
119  if (!svt_dec->decoder_initialized || ret != avctx->pix_fmt ||
120  avctx->width != svt_dec->config.width || avctx->height != svt_dec->config.height) {
121  if (svt_dec->decoder_initialized)
122  svt_jpeg_xs_decoder_close(&svt_dec->decoder);
123  err = svt_jpeg_xs_decoder_init(SVT_JPEGXS_API_VER_MAJOR, SVT_JPEGXS_API_VER_MINOR,
124  &svt_dec->decoder, avpkt->data, avpkt->size, &svt_dec->config);
125  if (err) {
126  av_log(avctx, AV_LOG_ERROR, "svt_jpeg_xs_decoder_init failed, err=%d\n", err);
127  return AVERROR_EXTERNAL;
128  }
129 
130  avctx->pix_fmt = ret;
131 
132  ret = ff_set_dimensions(avctx, svt_dec->config.width, svt_dec->config.height);
133  if (ret < 0) {
134  av_log(avctx, AV_LOG_ERROR, "ff_set_dimensions failed, err=%d\n", ret);
135  return ret;
136  }
137 
138  svt_dec->decoder_initialized = 1;
139  }
140 
141  if (avctx->skip_frame == AVDISCARD_ALL)
142  return 0;
143 
144  svt_dec->input.bitstream.buffer = avpkt->data;
145  svt_dec->input.bitstream.allocation_size = avpkt->size;
146  svt_dec->input.bitstream.used_size = avpkt->size;
147  svt_dec->input.user_prv_ctx_ptr = avpkt;
148 
149  ret = ff_get_buffer(avctx, picture, 0);
150  if (ret < 0)
151  return ret;
152 
153  unsigned pixel_shift = svt_dec->config.bit_depth <= 8 ? 0 : 1;
154  for (int comp = 0; comp < svt_dec->config.components_num; comp++) {
155  svt_dec->input.image.data_yuv[comp] = picture->data[comp];
156  svt_dec->input.image.stride[comp] = picture->linesize[comp] >> pixel_shift;
157  svt_dec->input.image.alloc_size[comp] = picture->linesize[comp] * svt_dec->config.components[comp].height;
158  }
159 
160  err = svt_jpeg_xs_decoder_send_frame(&svt_dec->decoder, &svt_dec->input, 1 /*blocking*/);
161  if (err) {
162  av_log(avctx, AV_LOG_ERROR, "svt_jpeg_xs_decoder_send_frame failed, err=%d\n", err);
163  return AVERROR_EXTERNAL;
164  }
165 
166  err = svt_jpeg_xs_decoder_get_frame(&svt_dec->decoder, &svt_dec->output, 1 /*blocking*/);
167  if (err) {
168  av_log(avctx, AV_LOG_ERROR, "svt_jpeg_xs_decoder_get_frame failed, err=%d\n", err);
169  return AVERROR_EXTERNAL;
170  }
171 
172  if (svt_dec->output.user_prv_ctx_ptr != avpkt) {
173  av_log(avctx, AV_LOG_ERROR, "Returned different user_prv_ctx_ptr than expected\n");
174  return AVERROR_EXTERNAL;
175  }
176 
177  *got_frame = 1;
178 
179  return avpkt->size;
180 }
181 
183 {
184  SvtJpegXsDecodeContext* svt_dec = avctx->priv_data;
185 
186  svt_jpeg_xs_decoder_close(&svt_dec->decoder);
187 
188  return 0;
189 }
190 
192 {
193  SvtJpegXsDecodeContext* svt_dec = avctx->priv_data;
194 
195  int log_level = av_log_get_level();
196  svt_dec->decoder.verbose = log_level < AV_LOG_DEBUG ? VERBOSE_ERRORS :
197  log_level == AV_LOG_DEBUG ? VERBOSE_SYSTEM_INFO : VERBOSE_WARNINGS;
198 
199  if (avctx->lowres == 1)
200  svt_dec->decoder.proxy_mode = proxy_mode_half;
201  else if (avctx->lowres == 2)
202  svt_dec->decoder.proxy_mode = proxy_mode_quarter;
203  else
204  svt_dec->decoder.proxy_mode = proxy_mode_full;
205 
206  int thread_count = avctx->thread_count ? avctx->thread_count : av_cpu_count();
207  svt_dec->decoder.threads_num = FFMIN(thread_count, 64);
208  svt_dec->decoder.use_cpu_flags = CPU_FLAGS_ALL;
209 
210  return 0;
211 }
212 
214  .p.name = "libsvtjpegxs",
215  CODEC_LONG_NAME("SVT JPEG XS(Scalable Video Technology for JPEG XS) decoder"),
216  .p.type = AVMEDIA_TYPE_VIDEO,
217  .p.id = AV_CODEC_ID_JPEGXS,
218  .priv_data_size = sizeof(SvtJpegXsDecodeContext),
222  .p.capabilities = AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_DR1,
223  .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
226  .p.max_lowres = 2,
227  .p.wrapper_name = "libsvtjpegxs",
228 };
SvtJpegXsDecodeContext::output
svt_jpeg_xs_frame_t output
Definition: libsvtjpegxsdec.c:43
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
comp
static void comp(unsigned char *dst, ptrdiff_t dst_stride, unsigned char *src, ptrdiff_t src_stride, int add)
Definition: eamad.c:79
AV_PIX_FMT_YUV422P14LE
@ AV_PIX_FMT_YUV422P14LE
planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
Definition: pixfmt.h:274
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:427
AVPacket::data
uint8_t * data
Definition: packet.h:588
svt_jpegxs_dec_decode
static int svt_jpegxs_dec_decode(AVCodecContext *avctx, AVFrame *picture, int *got_frame, AVPacket *avpkt)
Definition: libsvtjpegxsdec.c:93
SvtJpegXsDecodeContext::decoder_initialized
uint32_t decoder_initialized
Definition: libsvtjpegxsdec.c:44
SvtJpegXsDecodeContext::decoder
svt_jpeg_xs_decoder_api_t decoder
Definition: libsvtjpegxsdec.c:41
FF_CODEC_CAP_NOT_INIT_THREADSAFE
#define FF_CODEC_CAP_NOT_INIT_THREADSAFE
The codec is not known to be init-threadsafe (i.e.
Definition: codec_internal.h:34
FFCodec
Definition: codec_internal.h:127
ff_set_dimensions
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Check that the provided frame dimensions are valid and set them on the codec context.
Definition: utils.c:91
tf_sess_config.config
config
Definition: tf_sess_config.py:33
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:448
svt_jpegxs_dec_free
static av_cold int svt_jpegxs_dec_free(AVCodecContext *avctx)
Definition: libsvtjpegxsdec.c:182
close
static av_cold void close(AVCodecParserContext *s)
Definition: apv_parser.c:136
SvtJpegXsDecodeContext::proxy_mode
int proxy_mode
Definition: libsvtjpegxsdec.c:46
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
AV_PIX_FMT_YUV420P12LE
@ AV_PIX_FMT_YUV420P12LE
planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
Definition: pixfmt.h:268
AVCodecContext::skip_frame
enum AVDiscard skip_frame
Skip decoding for selected frames.
Definition: avcodec.h:1670
AVCodecContext::thread_count
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
Definition: avcodec.h:1569
ff_libsvtjpegxs_decoder
const FFCodec ff_libsvtjpegxs_decoder
Definition: libsvtjpegxsdec.c:213
AV_PIX_FMT_YUV420P10LE
@ AV_PIX_FMT_YUV420P10LE
planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
Definition: pixfmt.h:156
AV_PIX_FMT_YUV444P12LE
@ AV_PIX_FMT_YUV444P12LE
planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition: pixfmt.h:276
AV_PIX_FMT_YUV444P14LE
@ AV_PIX_FMT_YUV444P14LE
planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition: pixfmt.h:278
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
av_cold
#define av_cold
Definition: attributes.h:106
set_pix_fmt
static int set_pix_fmt(void *logctx, const svt_jpeg_xs_image_config_t *config)
Definition: libsvtjpegxsdec.c:49
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:347
frame_size
int frame_size
Definition: mxfenc.c:2487
AV_CODEC_CAP_OTHER_THREADS
#define AV_CODEC_CAP_OTHER_THREADS
Codec supports multithreading through a method other than slice- or frame-level multithreading.
Definition: codec.h:109
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
decode.h
svt_jpegxs_dec_init
static av_cold int svt_jpegxs_dec_init(AVCodecContext *avctx)
Definition: libsvtjpegxsdec.c:191
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:73
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:332
AV_PIX_FMT_YUV444P10LE
@ AV_PIX_FMT_YUV444P10LE
planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
Definition: pixfmt.h:162
AVDISCARD_ALL
@ AVDISCARD_ALL
discard all
Definition: defs.h:232
av_log_get_level
int av_log_get_level(void)
Get the current log level.
Definition: log.c:472
profiles.h
AV_PIX_FMT_YUV420P14LE
@ AV_PIX_FMT_YUV420P14LE
planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
Definition: pixfmt.h:270
av_cpu_count
int av_cpu_count(void)
Definition: cpu.c:222
AVCodecContext::lowres
int lowres
low resolution decoding, 1-> 1/2 size, 2->1/4 size
Definition: avcodec.h:1705
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1729
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:550
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
AVPacket::size
int size
Definition: packet.h:589
codec_internal.h
cpu.h
AV_PIX_FMT_YUV422P10LE
@ AV_PIX_FMT_YUV422P10LE
planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
Definition: pixfmt.h:158
FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM
#define FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM
The decoder extracts and fills its parameters even if the frame is skipped due to the skip_frame sett...
Definition: codec_internal.h:54
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
AV_CODEC_ID_JPEGXS
@ AV_CODEC_ID_JPEGXS
Definition: codec_id.h:334
common.h
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:179
AVCodecContext::height
int height
Definition: avcodec.h:600
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:639
avcodec.h
ret
ret
Definition: filter_design.txt:187
SvtJpegXsDecodeContext::input
svt_jpeg_xs_frame_t input
Definition: libsvtjpegxsdec.c:42
SvtJpegXsDecodeContext
Definition: libsvtjpegxsdec.c:39
AVCodecContext
main external API structure.
Definition: avcodec.h:439
AV_PIX_FMT_YUV444P
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:78
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:200
AV_PIX_FMT_YUV422P
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:77
mem.h
FF_CODEC_CAP_AUTO_THREADS
#define FF_CODEC_CAP_AUTO_THREADS
Codec handles avctx->thread_count == 0 (auto) internally.
Definition: codec_internal.h:72
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:466
AVPacket
This structure stores compressed data.
Definition: packet.h:565
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:600
imgutils.h
AVERROR_BUG
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:52
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:472
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
SvtJpegXsDecodeContext::config
svt_jpeg_xs_image_config_t config
Definition: libsvtjpegxsdec.c:40
AV_PIX_FMT_YUV422P12LE
@ AV_PIX_FMT_YUV422P12LE
planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
Definition: pixfmt.h:272