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 "decode.h"
27 #include "lcevcdec.h"
28 
29 #if CONFIG_LIBLCEVC_DEC
30 static LCEVC_ColorFormat map_format(int format)
31 {
32  switch (format) {
33  case AV_PIX_FMT_YUV420P:
34  return LCEVC_I420_8;
36  return LCEVC_I420_10_LE;
37  case AV_PIX_FMT_NV12:
38  return LCEVC_NV12_8;
39  case AV_PIX_FMT_NV21:
40  return LCEVC_NV21_8;
41  case AV_PIX_FMT_GRAY8:
42  return LCEVC_GRAY_8;
43  }
44 
45  return LCEVC_ColorFormat_Unknown;
46 }
47 
48 static int alloc_base_frame(void *logctx, LCEVC_DecoderHandle decoder,
49  const AVFrame *frame, LCEVC_PictureHandle *picture)
50 {
51  LCEVC_PictureDesc desc;
52  LCEVC_ColorFormat fmt = map_format(frame->format);
53  LCEVC_PictureLockHandle lock;
54  uint8_t *data[4] = { NULL };
55  int linesizes[4] = { 0 };
56  uint32_t planes;
57  LCEVC_ReturnCode res;
58 
59  res = LCEVC_DefaultPictureDesc(&desc, fmt, frame->width, frame->height);
60  if (res != LCEVC_Success)
61  return AVERROR_EXTERNAL;
62 
63  desc.cropTop = frame->crop_top;
64  desc.cropBottom = frame->crop_bottom;
65  desc.cropLeft = frame->crop_left;
66  desc.cropRight = frame->crop_right;
67  desc.sampleAspectRatioNum = frame->sample_aspect_ratio.num;
68  desc.sampleAspectRatioDen = frame->sample_aspect_ratio.den;
69 
70  /* Allocate LCEVC Picture */
71  res = LCEVC_AllocPicture(decoder, &desc, picture);
72  if (res != LCEVC_Success) {
73  return AVERROR_EXTERNAL;
74  }
75  res = LCEVC_LockPicture(decoder, *picture, LCEVC_Access_Write, &lock);
76  if (res != LCEVC_Success)
77  return AVERROR_EXTERNAL;
78 
79  res = LCEVC_GetPicturePlaneCount(decoder, *picture, &planes);
80  if (res != LCEVC_Success)
81  return AVERROR_EXTERNAL;
82 
83  for (unsigned i = 0; i < planes; i++) {
84  LCEVC_PicturePlaneDesc plane;
85 
86  res = LCEVC_GetPictureLockPlaneDesc(decoder, lock, i, &plane);
87  if (res != LCEVC_Success)
88  return AVERROR_EXTERNAL;
89 
90  data[i] = plane.firstSample;
91  linesizes[i] = plane.rowByteStride;
92  }
93 
94  av_image_copy2(data, linesizes, frame->data, frame->linesize,
95  frame->format, frame->width, frame->height);
96 
97  res = LCEVC_UnlockPicture(decoder, lock);
98  if (res != LCEVC_Success)
99  return AVERROR_EXTERNAL;
100 
101  return 0;
102 }
103 
104 static int alloc_enhanced_frame(void *logctx, LCEVC_DecoderHandle decoder,
105  const AVFrame *frame, LCEVC_PictureHandle *picture)
106 {
107  LCEVC_PictureDesc desc ;
108  LCEVC_ColorFormat fmt = map_format(frame->format);
109  LCEVC_PicturePlaneDesc planes[4] = { 0 };
110  int width = frame->width * 2 / FFMAX(frame->sample_aspect_ratio.den, 1);
111  int height = frame->height * 2 / FFMAX(frame->sample_aspect_ratio.num, 1);
112  LCEVC_ReturnCode res;
113 
114  res = LCEVC_DefaultPictureDesc(&desc, fmt, width, height);
115  if (res != LCEVC_Success)
116  return AVERROR_EXTERNAL;
117 
118  /* Set plane description */
119  for (int i = 0; i < 4; i++) {
120  planes[i].firstSample = frame->data[i];
121  planes[i].rowByteStride = frame->linesize[i];
122  }
123 
124  /* Allocate LCEVC Picture */
125  res = LCEVC_AllocPictureExternal(decoder, &desc, NULL, planes, picture);
126  if (res != LCEVC_Success) {
127  return AVERROR_EXTERNAL;
128  }
129  return 0;
130 }
131 
132 static int lcevc_send_frame(void *logctx, FFLCEVCContext *lcevc, const AVFrame *in)
133 {
135  LCEVC_PictureHandle picture;
136  LCEVC_ReturnCode res;
137  int ret = 0;
138 
139  if (!sd)
140  return 1;
141 
142  res = LCEVC_SendDecoderEnhancementData(lcevc->decoder, in->pts, 0, sd->data, sd->size);
143  if (res != LCEVC_Success)
144  return AVERROR_EXTERNAL;
145 
146  ret = alloc_base_frame(logctx, lcevc->decoder, in, &picture);
147  if (ret < 0)
148  return ret;
149 
150  res = LCEVC_SendDecoderBase(lcevc->decoder, in->pts, 0, picture, -1, NULL);
151  if (res != LCEVC_Success)
152  return AVERROR_EXTERNAL;
153 
154  memset(&picture, 0, sizeof(picture));
155  ret = alloc_enhanced_frame(logctx, lcevc->decoder, in, &picture);
156  if (ret < 0)
157  return ret;
158 
159  res = LCEVC_SendDecoderPicture(lcevc->decoder, picture);
160  if (res != LCEVC_Success)
161  return AVERROR_EXTERNAL;
162 
163  return 0;
164 }
165 
166 static int generate_output(void *logctx, FFLCEVCContext *lcevc, AVFrame *out)
167 {
168  LCEVC_PictureDesc desc;
169  LCEVC_DecodeInformation info;
170  LCEVC_PictureHandle picture;
171  LCEVC_ReturnCode res;
172 
173  res = LCEVC_ReceiveDecoderPicture(lcevc->decoder, &picture, &info);
174  if (res != LCEVC_Success)
175  return AVERROR_EXTERNAL;
176 
177  res = LCEVC_GetPictureDesc(lcevc->decoder, picture, &desc);
178  if (res != LCEVC_Success)
179  return AVERROR_EXTERNAL;
180 
181  out->crop_top = desc.cropTop;
182  out->crop_bottom = desc.cropBottom;
183  out->crop_left = desc.cropLeft;
184  out->crop_right = desc.cropRight;
185  out->sample_aspect_ratio.num = desc.sampleAspectRatioNum;
186  out->sample_aspect_ratio.den = desc.sampleAspectRatioDen;
187  out->width = desc.width + out->crop_left + out->crop_right;
188  out->height = desc.height + out->crop_top + out->crop_bottom;
189 
190  res = LCEVC_FreePicture(lcevc->decoder, picture);
191  if (res != LCEVC_Success)
192  return AVERROR_EXTERNAL;
193 
194  return 0;
195 }
196 
197 static int lcevc_receive_frame(void *logctx, FFLCEVCContext *lcevc, AVFrame *out)
198 {
199  LCEVC_PictureHandle picture;
200  LCEVC_ReturnCode res;
201  int ret;
202 
203  ret = generate_output(logctx, lcevc, out);
204  if (ret < 0)
205  return ret;
206 
207  while (1) {
208  res = LCEVC_ReceiveDecoderBase (lcevc->decoder, &picture);
209  if (res != LCEVC_Success && res != LCEVC_Again)
210  return AVERROR_EXTERNAL;
211 
212  if (res == LCEVC_Again)
213  break;
214 
215  res = LCEVC_FreePicture(lcevc->decoder, picture);
216  if (res != LCEVC_Success)
217  return AVERROR_EXTERNAL;
218  }
219 
220  return 0;
221 }
222 
223 static void event_callback(LCEVC_DecoderHandle dec, LCEVC_Event event,
224  LCEVC_PictureHandle pic, const LCEVC_DecodeInformation *info,
225  const uint8_t *data, uint32_t size, void *logctx)
226 {
227  switch (event) {
228  case LCEVC_Log:
229  av_log(logctx, AV_LOG_INFO, "%s\n", data);
230  break;
231  default:
232  break;
233  }
234 }
235 
236 static void lcevc_free(FFRefStructOpaque unused, void *obj)
237 {
238  FFLCEVCContext *lcevc = obj;
239  if (lcevc->initialized)
240  LCEVC_DestroyDecoder(lcevc->decoder);
241  memset(lcevc, 0, sizeof(*lcevc));
242 }
243 #endif
244 
245 static int lcevc_init(FFLCEVCContext *lcevc, void *logctx)
246 {
247 #if CONFIG_LIBLCEVC_DEC
248  LCEVC_AccelContextHandle dummy = { 0 };
249  const int32_t event = LCEVC_Log;
250 #endif
251 
252  if (lcevc->initialized)
253  return 0;
254 
255 #if CONFIG_LIBLCEVC_DEC
256  if (LCEVC_CreateDecoder(&lcevc->decoder, dummy) != LCEVC_Success) {
257  av_log(logctx, AV_LOG_ERROR, "Failed to create LCEVC decoder\n");
258  return AVERROR_EXTERNAL;
259  }
260 
261  LCEVC_ConfigureDecoderInt(lcevc->decoder, "log_level", 4);
262  LCEVC_ConfigureDecoderIntArray(lcevc->decoder, "events", 1, &event);
263  LCEVC_SetDecoderEventCallback(lcevc->decoder, event_callback, logctx);
264 
265  if (LCEVC_InitializeDecoder(lcevc->decoder) != LCEVC_Success) {
266  av_log(logctx, AV_LOG_ERROR, "Failed to initialize LCEVC decoder\n");
267  LCEVC_DestroyDecoder(lcevc->decoder);
268  return AVERROR_EXTERNAL;
269  }
270 
271 #endif
272  lcevc->initialized = 1;
273 
274  return 0;
275 }
276 
277 int ff_lcevc_process(void *logctx, AVFrame *frame)
278 {
279  FrameDecodeData *fdd = (FrameDecodeData*)frame->private_ref->data;
280  FFLCEVCContext *lcevc = fdd->post_process_opaque;
281  int ret;
282 
283  if (!lcevc->initialized) {
284  ret = lcevc_init(lcevc, logctx);
285  if (ret < 0)
286  return ret;
287  }
288 
289 #if CONFIG_LIBLCEVC_DEC
290  ret = lcevc_send_frame(logctx, lcevc, frame);
291  if (ret)
292  return ret < 0 ? ret : 0;
293 
294  lcevc_receive_frame(logctx, lcevc, frame);
295  if (ret < 0)
296  return ret;
297 
299 #endif
300 
301  return 0;
302 }
303 
305 {
306  FFLCEVCContext *lcevc = NULL;
307 #if CONFIG_LIBLCEVC_DEC
308  lcevc = ff_refstruct_alloc_ext(sizeof(*lcevc), 0, NULL, lcevc_free);
309  if (!lcevc)
310  return AVERROR(ENOMEM);
311 #endif
312  *plcevc = lcevc;
313  return 0;
314 }
315 
316 void ff_lcevc_unref(void *opaque)
317 {
318  ff_refstruct_unref(&opaque);
319 }
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:963
ff_lcevc_alloc
int ff_lcevc_alloc(FFLCEVCContext **plcevc)
Definition: lcevcdec.c:304
ff_refstruct_alloc_ext
static void * ff_refstruct_alloc_ext(size_t size, unsigned flags, void *opaque, void(*free_cb)(FFRefStructOpaque opaque, void *obj))
A wrapper around ff_refstruct_alloc_ext_c() for the common case of a non-const qualified opaque.
Definition: refstruct.h:94
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:389
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:501
FFLCEVCContext
Definition: lcevcdec.h:32
data
const char data[16]
Definition: mxf.c:149
lcevc_init
static int lcevc_init(FFLCEVCContext *lcevc, void *logctx)
Definition: lcevcdec.c:245
AV_PIX_FMT_YUV420P10
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:502
FFLCEVCContext::initialized
int initialized
Definition: lcevcdec.h:34
FFRefStructOpaque
RefStruct is an API for creating reference-counted objects with minimal overhead.
Definition: refstruct.h:58
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:33
planes
static const struct @466 planes[]
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:277
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
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:316
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:81
height
#define height
Definition: dsp.h:85
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:1029
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
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
ff_refstruct_unref
void ff_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
Definition: refstruct.c:120