FFmpeg
lcevcdec.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include "config_components.h"
20 
21 #include "libavutil/avassert.h"
22 #include "libavutil/frame.h"
23 #include "libavutil/imgutils.h"
24 #include "libavutil/log.h"
25 #include "libavutil/mem.h"
26 #include "libavutil/refstruct.h"
27 
28 #include "decode.h"
29 #include "lcevcdec.h"
30 
31 #if CONFIG_LIBLCEVC_DEC
32 static LCEVC_ColorFormat map_format(int format)
33 {
34  switch (format) {
35  case AV_PIX_FMT_YUV420P:
36  return LCEVC_I420_8;
38  return LCEVC_I420_10_LE;
39  case AV_PIX_FMT_NV12:
40  return LCEVC_NV12_8;
41  case AV_PIX_FMT_NV21:
42  return LCEVC_NV21_8;
43  case AV_PIX_FMT_GRAY8:
44  return LCEVC_GRAY_8;
45  }
46 
47  return LCEVC_ColorFormat_Unknown;
48 }
49 
50 static int alloc_base_frame(void *logctx, LCEVC_DecoderHandle decoder,
51  const AVFrame *frame, LCEVC_PictureHandle *picture)
52 {
53  LCEVC_PictureDesc desc;
54  LCEVC_ColorFormat fmt = map_format(frame->format);
55  LCEVC_PictureLockHandle lock;
56  uint8_t *data[4] = { NULL };
57  int linesizes[4] = { 0 };
58  uint32_t planes;
59  LCEVC_ReturnCode res;
60 
61  res = LCEVC_DefaultPictureDesc(&desc, fmt, frame->width, frame->height);
62  if (res != LCEVC_Success)
63  return AVERROR_EXTERNAL;
64 
65  desc.cropTop = frame->crop_top;
66  desc.cropBottom = frame->crop_bottom;
67  desc.cropLeft = frame->crop_left;
68  desc.cropRight = frame->crop_right;
69  desc.sampleAspectRatioNum = frame->sample_aspect_ratio.num;
70  desc.sampleAspectRatioDen = frame->sample_aspect_ratio.den;
71 
72  /* Allocate LCEVC Picture */
73  res = LCEVC_AllocPicture(decoder, &desc, picture);
74  if (res != LCEVC_Success) {
75  return AVERROR_EXTERNAL;
76  }
77  res = LCEVC_LockPicture(decoder, *picture, LCEVC_Access_Write, &lock);
78  if (res != LCEVC_Success)
79  return AVERROR_EXTERNAL;
80 
81  res = LCEVC_GetPicturePlaneCount(decoder, *picture, &planes);
82  if (res != LCEVC_Success)
83  return AVERROR_EXTERNAL;
84 
85  for (unsigned i = 0; i < planes; i++) {
86  LCEVC_PicturePlaneDesc plane;
87 
88  res = LCEVC_GetPictureLockPlaneDesc(decoder, lock, i, &plane);
89  if (res != LCEVC_Success)
90  return AVERROR_EXTERNAL;
91 
92  data[i] = plane.firstSample;
93  linesizes[i] = plane.rowByteStride;
94  }
95 
96  av_image_copy2(data, linesizes, frame->data, frame->linesize,
97  frame->format, frame->width, frame->height);
98 
99  res = LCEVC_UnlockPicture(decoder, lock);
100  if (res != LCEVC_Success)
101  return AVERROR_EXTERNAL;
102 
103  return 0;
104 }
105 
106 static int alloc_enhanced_frame(void *logctx, LCEVC_DecoderHandle decoder,
107  const AVFrame *frame, LCEVC_PictureHandle *picture)
108 {
109  LCEVC_PictureDesc desc ;
110  LCEVC_ColorFormat fmt = map_format(frame->format);
111  LCEVC_PicturePlaneDesc planes[4] = { 0 };
112  int width = frame->width * 2 / FFMAX(frame->sample_aspect_ratio.den, 1);
113  int height = frame->height * 2 / FFMAX(frame->sample_aspect_ratio.num, 1);
114  LCEVC_ReturnCode res;
115 
116  res = LCEVC_DefaultPictureDesc(&desc, fmt, width, height);
117  if (res != LCEVC_Success)
118  return AVERROR_EXTERNAL;
119 
120  /* Set plane description */
121  for (int i = 0; i < 4; i++) {
122  planes[i].firstSample = frame->data[i];
123  planes[i].rowByteStride = frame->linesize[i];
124  }
125 
126  /* Allocate LCEVC Picture */
127  res = LCEVC_AllocPictureExternal(decoder, &desc, NULL, planes, picture);
128  if (res != LCEVC_Success) {
129  return AVERROR_EXTERNAL;
130  }
131  return 0;
132 }
133 
134 static int lcevc_send_frame(void *logctx, FFLCEVCContext *lcevc, const AVFrame *in)
135 {
137  LCEVC_PictureHandle picture;
138  LCEVC_ReturnCode res;
139  int ret = 0;
140 
141  if (!sd)
142  return 1;
143 
144  res = LCEVC_SendDecoderEnhancementData(lcevc->decoder, in->pts, 0, sd->data, sd->size);
145  if (res != LCEVC_Success)
146  return AVERROR_EXTERNAL;
147 
148  ret = alloc_base_frame(logctx, lcevc->decoder, in, &picture);
149  if (ret < 0)
150  return ret;
151 
152  res = LCEVC_SendDecoderBase(lcevc->decoder, in->pts, 0, picture, -1, NULL);
153  if (res != LCEVC_Success)
154  return AVERROR_EXTERNAL;
155 
156  memset(&picture, 0, sizeof(picture));
157  ret = alloc_enhanced_frame(logctx, lcevc->decoder, in, &picture);
158  if (ret < 0)
159  return ret;
160 
161  res = LCEVC_SendDecoderPicture(lcevc->decoder, picture);
162  if (res != LCEVC_Success)
163  return AVERROR_EXTERNAL;
164 
165  return 0;
166 }
167 
168 static int generate_output(void *logctx, FFLCEVCContext *lcevc, AVFrame *out)
169 {
170  LCEVC_PictureDesc desc;
171  LCEVC_DecodeInformation info;
172  LCEVC_PictureHandle picture;
173  LCEVC_ReturnCode res;
174 
175  res = LCEVC_ReceiveDecoderPicture(lcevc->decoder, &picture, &info);
176  if (res != LCEVC_Success)
177  return AVERROR_EXTERNAL;
178 
179  res = LCEVC_GetPictureDesc(lcevc->decoder, picture, &desc);
180  if (res != LCEVC_Success)
181  return AVERROR_EXTERNAL;
182 
183  out->crop_top = desc.cropTop;
184  out->crop_bottom = desc.cropBottom;
185  out->crop_left = desc.cropLeft;
186  out->crop_right = desc.cropRight;
187  out->sample_aspect_ratio.num = desc.sampleAspectRatioNum;
188  out->sample_aspect_ratio.den = desc.sampleAspectRatioDen;
189  out->width = desc.width + out->crop_left + out->crop_right;
190  out->height = desc.height + out->crop_top + out->crop_bottom;
191 
192  res = LCEVC_FreePicture(lcevc->decoder, picture);
193  if (res != LCEVC_Success)
194  return AVERROR_EXTERNAL;
195 
196  return 0;
197 }
198 
199 static int lcevc_receive_frame(void *logctx, FFLCEVCContext *lcevc, AVFrame *out)
200 {
201  LCEVC_PictureHandle picture;
202  LCEVC_ReturnCode res;
203  int ret;
204 
205  ret = generate_output(logctx, lcevc, out);
206  if (ret < 0)
207  return ret;
208 
209  while (1) {
210  res = LCEVC_ReceiveDecoderBase (lcevc->decoder, &picture);
211  if (res != LCEVC_Success && res != LCEVC_Again)
212  return AVERROR_EXTERNAL;
213 
214  if (res == LCEVC_Again)
215  break;
216 
217  res = LCEVC_FreePicture(lcevc->decoder, picture);
218  if (res != LCEVC_Success)
219  return AVERROR_EXTERNAL;
220  }
221 
222  return 0;
223 }
224 
225 static void event_callback(LCEVC_DecoderHandle dec, LCEVC_Event event,
226  LCEVC_PictureHandle pic, const LCEVC_DecodeInformation *info,
227  const uint8_t *data, uint32_t size, void *logctx)
228 {
229  switch (event) {
230  case LCEVC_Log:
231  av_log(logctx, AV_LOG_INFO, "%s\n", data);
232  break;
233  default:
234  break;
235  }
236 }
237 
238 static void lcevc_free(AVRefStructOpaque unused, void *obj)
239 {
240  FFLCEVCContext *lcevc = obj;
241  if (lcevc->initialized)
242  LCEVC_DestroyDecoder(lcevc->decoder);
243  memset(lcevc, 0, sizeof(*lcevc));
244 }
245 #endif
246 
247 static int lcevc_init(FFLCEVCContext *lcevc, void *logctx)
248 {
249 #if CONFIG_LIBLCEVC_DEC
250  LCEVC_AccelContextHandle dummy = { 0 };
251  const int32_t event = LCEVC_Log;
252 #endif
253 
254  if (lcevc->initialized)
255  return 0;
256 
257 #if CONFIG_LIBLCEVC_DEC
258  if (LCEVC_CreateDecoder(&lcevc->decoder, dummy) != LCEVC_Success) {
259  av_log(logctx, AV_LOG_ERROR, "Failed to create LCEVC decoder\n");
260  return AVERROR_EXTERNAL;
261  }
262 
263  LCEVC_ConfigureDecoderInt(lcevc->decoder, "log_level", 4);
264  LCEVC_ConfigureDecoderIntArray(lcevc->decoder, "events", 1, &event);
265  LCEVC_SetDecoderEventCallback(lcevc->decoder, event_callback, logctx);
266 
267  if (LCEVC_InitializeDecoder(lcevc->decoder) != LCEVC_Success) {
268  av_log(logctx, AV_LOG_ERROR, "Failed to initialize LCEVC decoder\n");
269  LCEVC_DestroyDecoder(lcevc->decoder);
270  return AVERROR_EXTERNAL;
271  }
272 
273 #endif
274  lcevc->initialized = 1;
275 
276  return 0;
277 }
278 
279 int ff_lcevc_process(void *logctx, AVFrame *frame)
280 {
281  FrameDecodeData *fdd = (FrameDecodeData*)frame->private_ref->data;
282  FFLCEVCContext *lcevc = fdd->post_process_opaque;
283  int ret;
284 
285  if (!lcevc->initialized) {
286  ret = lcevc_init(lcevc, logctx);
287  if (ret < 0)
288  return ret;
289  }
290 
291 #if CONFIG_LIBLCEVC_DEC
292  ret = lcevc_send_frame(logctx, lcevc, frame);
293  if (ret)
294  return ret < 0 ? ret : 0;
295 
296  lcevc_receive_frame(logctx, lcevc, frame);
297  if (ret < 0)
298  return ret;
299 
301 #endif
302 
303  return 0;
304 }
305 
307 {
308  FFLCEVCContext *lcevc = NULL;
309 #if CONFIG_LIBLCEVC_DEC
310  lcevc = av_refstruct_alloc_ext(sizeof(*lcevc), 0, NULL, lcevc_free);
311  if (!lcevc)
312  return AVERROR(ENOMEM);
313 #endif
314  *plcevc = lcevc;
315  return 0;
316 }
317 
318 void ff_lcevc_unref(void *opaque)
319 {
320  av_refstruct_unref(&opaque);
321 }
lcevcdec.h
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
out
FILE * out
Definition: movenc.c:55
av_frame_get_side_data
AVFrameSideData * av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type)
Definition: frame.c:980
ff_lcevc_alloc
int ff_lcevc_alloc(FFLCEVCContext **plcevc)
Definition: lcevcdec.c:306
AVRefStructOpaque
RefStruct is an API for creating reference-counted objects with minimal overhead.
Definition: refstruct.h:58
FrameDecodeData
This struct stores per-frame lavc-internal data and is attached to it via private_ref.
Definition: decode.h:33
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:403
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:515
FFLCEVCContext
Definition: lcevcdec.h:31
data
const char data[16]
Definition: mxf.c:149
lcevc_init
static int lcevc_init(FFLCEVCContext *lcevc, void *logctx)
Definition: lcevcdec.c:247
AV_PIX_FMT_YUV420P10
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:502
FFLCEVCContext::initialized
int initialized
Definition: lcevcdec.h:33
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
map_format
static LCEVC_ColorFormat map_format(int format)
Definition: vf_lcevc.c:35
FFLCEVCContext::decoder
LCEVC_DecoderHandle decoder
Definition: lcevcdec.h:32
decoder
static const chunk_decoder decoder[8]
Definition: dfa.c:331
dummy
int dummy
Definition: motion.c:66
ff_lcevc_process
int ff_lcevc_process(void *logctx, AVFrame *frame)
Definition: lcevcdec.c:279
refstruct.h
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
AVFrameSideData::size
size_t size
Definition: frame.h:268
FrameDecodeData::post_process_opaque
void * post_process_opaque
Definition: decode.h:45
format
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 format(the sample packing is implied by the sample format) and sample rate. The lists are not just lists
info
MIPS optimizations info
Definition: mips.txt:2
av_refstruct_alloc_ext
static void * av_refstruct_alloc_ext(size_t size, unsigned flags, void *opaque, void(*free_cb)(AVRefStructOpaque opaque, void *obj))
A wrapper around av_refstruct_alloc_ext_c() for the common case of a non-const qualified opaque.
Definition: refstruct.h:94
decode.h
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
alloc_enhanced_frame
static int alloc_enhanced_frame(AVFilterLink *inlink, const AVFrame *out, LCEVC_PictureHandle *picture)
Definition: vf_lcevc.c:161
generate_output
static int generate_output(AVFilterLink *inlink, AVFrame *out)
Definition: vf_lcevc.c:189
if
if(ret)
Definition: filter_design.txt:179
NULL
#define NULL
Definition: coverity.c:32
ff_lcevc_unref
void ff_lcevc_unref(void *opaque)
Definition: lcevcdec.c:318
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:81
height
#define height
Definition: dsp.h:85
planes
static const struct @472 planes[]
AV_FRAME_DATA_LCEVC
@ AV_FRAME_DATA_LCEVC
Raw LCEVC payload data, as a uint8_t array, with NAL emulation bytes intact.
Definition: frame.h:236
size
int size
Definition: twinvq_data.h:10344
LCEVC_DecoderHandle
uintptr_t LCEVC_DecoderHandle
Definition: lcevcdec.h:28
alloc_base_frame
static int alloc_base_frame(AVFilterLink *inlink, const AVFrame *in, LCEVC_PictureHandle *picture)
Definition: vf_lcevc.c:79
AVFrameSideData::data
uint8_t * data
Definition: frame.h:267
frame.h
av_frame_remove_side_data
void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type)
Remove and free all side data instances of the given type.
Definition: frame.c:1046
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:220
av_refstruct_unref
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
Definition: refstruct.c:120
lock
static pthread_mutex_t lock
Definition: ffjni.c:39
log.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
AV_PIX_FMT_NV21
@ AV_PIX_FMT_NV21
as above, but U and V bytes are swapped
Definition: pixfmt.h:97
ret
ret
Definition: filter_design.txt:187
AV_PIX_FMT_NV12
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:96
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
av_image_copy2
static void av_image_copy2(uint8_t *const dst_data[4], const int dst_linesizes[4], uint8_t *const src_data[4], const int src_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height)
Wrapper around av_image_copy() to workaround the limitation that the conversion from uint8_t * const ...
Definition: imgutils.h:184
desc
const char * desc
Definition: libsvtav1.c:79
mem.h
AVFrameSideData
Structure to hold side data for an AVFrame.
Definition: frame.h:265
int32_t
int32_t
Definition: audioconvert.c:56
imgutils.h
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
width
#define width
Definition: dsp.h:85