FFmpeg
cbs_sei.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 "cbs.h"
20 #include "cbs_internal.h"
21 #include "cbs_h264.h"
22 #include "cbs_h265.h"
23 #include "cbs_sei.h"
24 
25 static void cbs_free_user_data_registered(void *opaque, uint8_t *data)
26 {
29  av_free(udr);
30 }
31 
32 static void cbs_free_user_data_unregistered(void *opaque, uint8_t *data)
33 {
36  av_free(udu);
37 }
38 
41 {
42  void (*free_func)(void*, uint8_t*);
43 
44  av_assert0(message->payload == NULL &&
45  message->payload_ref == NULL);
46  message->payload_type = desc->type;
47 
49  free_func = &cbs_free_user_data_registered;
50  else if (desc->type == SEI_TYPE_USER_DATA_UNREGISTERED)
52  else
53  free_func = NULL;
54 
55  if (free_func) {
56  message->payload = av_mallocz(desc->size);
57  if (!message->payload)
58  return AVERROR(ENOMEM);
59  message->payload_ref =
60  av_buffer_create(message->payload, desc->size,
61  free_func, NULL, 0);
62  } else {
63  message->payload_ref = av_buffer_alloc(desc->size);
64  }
65  if (!message->payload_ref) {
66  av_freep(&message->payload);
67  return AVERROR(ENOMEM);
68  }
69  message->payload = message->payload_ref->data;
70 
71  return 0;
72 }
73 
75 {
76  void *ptr;
77  int old_count = list->nb_messages_allocated;
78 
79  av_assert0(list->nb_messages <= old_count);
80  if (list->nb_messages + 1 > old_count) {
81  int new_count = 2 * old_count + 1;
82 
83  ptr = av_realloc_array(list->messages,
84  new_count, sizeof(*list->messages));
85  if (!ptr)
86  return AVERROR(ENOMEM);
87 
88  list->messages = ptr;
89  list->nb_messages_allocated = new_count;
90 
91  // Zero the newly-added entries.
92  memset(list->messages + old_count, 0,
93  (new_count - old_count) * sizeof(*list->messages));
94  }
95  ++list->nb_messages;
96  return 0;
97 }
98 
100 {
101  for (int i = 0; i < list->nb_messages; i++) {
102  SEIRawMessage *message = &list->messages[i];
103  av_buffer_unref(&message->payload_ref);
104  av_buffer_unref(&message->extension_data_ref);
105  }
106  av_free(list->messages);
107 }
108 
111  int prefix,
112  CodedBitstreamUnit **sei_unit)
113 {
114  CodedBitstreamUnit *unit;
115  int sei_type, highest_vcl_type, err, i, position;
116 
117  switch (ctx->codec->codec_id) {
118  case AV_CODEC_ID_H264:
119  // (We can ignore auxiliary slices because we only have prefix
120  // SEI in H.264 and an auxiliary picture must always follow a
121  // primary picture.)
122  highest_vcl_type = H264_NAL_IDR_SLICE;
123  if (prefix)
124  sei_type = H264_NAL_SEI;
125  else
126  return AVERROR(EINVAL);
127  break;
128  case AV_CODEC_ID_H265:
129  highest_vcl_type = HEVC_NAL_RSV_VCL31;
130  if (prefix)
131  sei_type = HEVC_NAL_SEI_PREFIX;
132  else
133  sei_type = HEVC_NAL_SEI_SUFFIX;
134  break;
135  default:
136  return AVERROR(EINVAL);
137  }
138 
139  // Find an existing SEI NAL unit of the right type.
140  unit = NULL;
141  for (i = 0; i < au->nb_units; i++) {
142  if (au->units[i].type == sei_type) {
143  unit = &au->units[i];
144  break;
145  }
146  }
147 
148  if (unit) {
149  *sei_unit = unit;
150  return 0;
151  }
152 
153  // Need to add a new SEI NAL unit ...
154  if (prefix) {
155  // ... before the first VCL NAL unit.
156  for (i = 0; i < au->nb_units; i++) {
157  if (au->units[i].type < highest_vcl_type)
158  break;
159  }
160  position = i;
161  } else {
162  // ... after the last VCL NAL unit.
163  for (i = au->nb_units - 1; i >= 0; i--) {
164  if (au->units[i].type < highest_vcl_type)
165  break;
166  }
167  if (i < 0) {
168  // No VCL units; just put it at the end.
169  position = au->nb_units;
170  } else {
171  position = i + 1;
172  }
173  }
174 
175  err = ff_cbs_insert_unit_content(au, position, sei_type,
176  NULL, NULL);
177  if (err < 0)
178  return err;
179  unit = &au->units[position];
180  unit->type = sei_type;
181 
182  err = ff_cbs_alloc_unit_content2(ctx, unit);
183  if (err < 0)
184  return err;
185 
186  switch (ctx->codec->codec_id) {
187  case AV_CODEC_ID_H264:
188  {
189  H264RawSEI sei = {
190  .nal_unit_header = {
191  .nal_ref_idc = 0,
192  .nal_unit_type = sei_type,
193  },
194  };
195  memcpy(unit->content, &sei, sizeof(sei));
196  }
197  break;
198  case AV_CODEC_ID_H265:
199  {
200  H265RawSEI sei = {
201  .nal_unit_header = {
202  .nal_unit_type = sei_type,
203  .nuh_layer_id = 0,
204  .nuh_temporal_id_plus1 = 1,
205  },
206  };
207  memcpy(unit->content, &sei, sizeof(sei));
208  }
209  break;
210  default:
211  av_assert0(0);
212  }
213 
214  *sei_unit = unit;
215  return 0;
216 }
217 
219  CodedBitstreamUnit *unit,
221 {
222  switch (ctx->codec->codec_id) {
223  case AV_CODEC_ID_H264:
224  {
225  H264RawSEI *sei = unit->content;
226  if (unit->type != H264_NAL_SEI)
227  return AVERROR(EINVAL);
228  *list = &sei->message_list;
229  }
230  break;
231  case AV_CODEC_ID_H265:
232  {
233  H265RawSEI *sei = unit->content;
234  if (unit->type != HEVC_NAL_SEI_PREFIX &&
235  unit->type != HEVC_NAL_SEI_SUFFIX)
236  return AVERROR(EINVAL);
237  *list = &sei->message_list;
238  }
239  break;
240  default:
241  return AVERROR(EINVAL);
242  }
243 
244  return 0;
245 }
246 
249  int prefix,
250  uint32_t payload_type,
251  void *payload_data,
252  AVBufferRef *payload_buf)
253 {
255  CodedBitstreamUnit *unit;
258  AVBufferRef *payload_ref;
259  int err;
260 
261  desc = ff_cbs_sei_find_type(ctx, payload_type);
262  if (!desc)
263  return AVERROR(EINVAL);
264 
265  // Find an existing SEI unit or make a new one to add to.
266  err = cbs_sei_get_unit(ctx, au, prefix, &unit);
267  if (err < 0)
268  return err;
269 
270  // Find the message list inside the codec-dependent unit.
271  err = cbs_sei_get_message_list(ctx, unit, &list);
272  if (err < 0)
273  return err;
274 
275  // Add a new message to the message list.
276  err = ff_cbs_sei_list_add(list);
277  if (err < 0)
278  return err;
279 
280  if (payload_buf) {
281  payload_ref = av_buffer_ref(payload_buf);
282  if (!payload_ref)
283  return AVERROR(ENOMEM);
284  } else {
285  payload_ref = NULL;
286  }
287 
288  message = &list->messages[list->nb_messages - 1];
289 
290  message->payload_type = payload_type;
291  message->payload = payload_data;
292  message->payload_ref = payload_ref;
293 
294  return 0;
295 }
296 
299  uint32_t payload_type,
300  SEIRawMessage **iter)
301 {
302  int err, i, j, found;
303 
304  found = 0;
305  for (i = 0; i < au->nb_units; i++) {
306  CodedBitstreamUnit *unit = &au->units[i];
308 
309  err = cbs_sei_get_message_list(ctx, unit, &list);
310  if (err < 0)
311  continue;
312 
313  for (j = 0; j < list->nb_messages; j++) {
314  SEIRawMessage *message = &list->messages[j];
315 
316  if (message->payload_type == payload_type) {
317  if (!*iter || found) {
318  *iter = message;
319  return 0;
320  }
321  if (message == *iter)
322  found = 1;
323  }
324  }
325  }
326 
327  return AVERROR(ENOENT);
328 }
329 
331  int position)
332 {
334 
335  av_assert0(0 <= position && position < list->nb_messages);
336 
337  message = &list->messages[position];
338  av_buffer_unref(&message->payload_ref);
339  av_buffer_unref(&message->extension_data_ref);
340 
341  --list->nb_messages;
342 
343  if (list->nb_messages > 0) {
344  memmove(list->messages + position,
345  list->messages + position + 1,
346  (list->nb_messages - position) * sizeof(*list->messages));
347  }
348 }
349 
352  uint32_t payload_type)
353 {
354  int err, i, j;
355 
356  for (i = 0; i < au->nb_units; i++) {
357  CodedBitstreamUnit *unit = &au->units[i];
359 
360  err = cbs_sei_get_message_list(ctx, unit, &list);
361  if (err < 0)
362  continue;
363 
364  for (j = list->nb_messages - 1; j >= 0; j--) {
365  if (list->messages[j].payload_type == payload_type)
367  }
368  }
369 }
SEIRawUserDataRegistered::data_ref
AVBufferRef * data_ref
Definition: cbs_sei.h:39
ff_cbs_sei_add_message
int ff_cbs_sei_add_message(CodedBitstreamContext *ctx, CodedBitstreamFragment *au, int prefix, uint32_t payload_type, void *payload_data, AVBufferRef *payload_buf)
Add an SEI message to an access unit.
Definition: cbs_sei.c:247
H264_NAL_IDR_SLICE
@ H264_NAL_IDR_SLICE
Definition: h264.h:39
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
SEIRawUserDataRegistered
Definition: cbs_sei.h:35
message
Definition: api-threadmessage-test.c:46
cbs_h264.h
CodedBitstreamUnit::content
void * content
Pointer to the decomposed form of this unit.
Definition: cbs.h:106
H264_NAL_SEI
@ H264_NAL_SEI
Definition: h264.h:40
SEIRawMessage
Definition: cbs_sei.h:68
cbs_free_user_data_unregistered
static void cbs_free_user_data_unregistered(void *opaque, uint8_t *data)
Definition: cbs_sei.c:32
H265RawSEI
Definition: cbs_h265.h:673
ff_cbs_sei_delete_message_type
void ff_cbs_sei_delete_message_type(CodedBitstreamContext *ctx, CodedBitstreamFragment *au, uint32_t payload_type)
Delete all messages with the given payload type from an access unit.
Definition: cbs_sei.c:350
CodedBitstreamContext
Context structure for coded bitstream operations.
Definition: cbs.h:173
cbs_sei_get_message_list
static int cbs_sei_get_message_list(CodedBitstreamContext *ctx, CodedBitstreamUnit *unit, SEIRawMessageList **list)
Definition: cbs_sei.c:218
data
const char data[16]
Definition: mxf.c:143
ff_cbs_alloc_unit_content2
int ff_cbs_alloc_unit_content2(CodedBitstreamContext *ctx, CodedBitstreamUnit *unit)
Allocate a new internal content buffer matching the type of the unit.
Definition: cbs.c:888
CodedBitstreamUnit::type
CodedBitstreamUnitType type
Codec-specific type of this unit.
Definition: cbs.h:73
cbs.h
cbs_h265.h
av_buffer_ref
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:103
cbs_free_user_data_registered
static void cbs_free_user_data_registered(void *opaque, uint8_t *data)
Definition: cbs_sei.c:25
CodedBitstreamUnit
Coded bitstream unit structure.
Definition: cbs.h:69
SEIRawUserDataUnregistered
Definition: cbs_sei.h:43
CodedBitstreamFragment::units
CodedBitstreamUnit * units
Pointer to an array of units of length nb_units_allocated.
Definition: cbs.h:167
CodedBitstreamFragment
Coded bitstream fragment structure, combining one or more units.
Definition: cbs.h:121
HEVC_NAL_RSV_VCL31
@ HEVC_NAL_RSV_VCL31
Definition: hevc.h:60
av_realloc_array
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:224
SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35
@ SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35
Definition: sei.h:34
SEIRawMessageList
Definition: cbs_sei.h:78
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
ctx
AVFormatContext * ctx
Definition: movenc.c:48
cbs_internal.h
ff_cbs_sei_alloc_message_payload
int ff_cbs_sei_alloc_message_payload(SEIRawMessage *message, const SEIMessageTypeDescriptor *desc)
Allocate a new payload for the given SEI message.
Definition: cbs_sei.c:39
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: codec_id.h:77
NULL
#define NULL
Definition: coverity.c:32
av_buffer_unref
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition: buffer.c:139
cbs_sei.h
ff_cbs_insert_unit_content
int ff_cbs_insert_unit_content(CodedBitstreamFragment *frag, int position, CodedBitstreamUnitType type, void *content, AVBufferRef *content_buf)
Insert a new unit into a fragment with the given content.
Definition: cbs.c:756
SEIMessageTypeDescriptor
Definition: cbs_sei.h:113
list
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 list
Definition: filter_design.txt:25
HEVC_NAL_SEI_SUFFIX
@ HEVC_NAL_SEI_SUFFIX
Definition: hevc.h:69
sei
static int FUNC() sei(CodedBitstreamContext *ctx, RWContext *rw, H264RawSEI *current)
Definition: cbs_h264_syntax_template.c:825
SEI_TYPE_USER_DATA_UNREGISTERED
@ SEI_TYPE_USER_DATA_UNREGISTERED
Definition: sei.h:35
av_buffer_create
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:55
av_buffer_alloc
AVBufferRef * av_buffer_alloc(size_t size)
Allocate an AVBuffer of the given size using av_malloc().
Definition: buffer.c:77
ff_cbs_sei_find_type
const SEIMessageTypeDescriptor * ff_cbs_sei_find_type(CodedBitstreamContext *ctx, int payload_type)
Find the type descriptor for the given payload type.
Definition: cbs_h2645.c:1652
cbs_sei_delete_message
static void cbs_sei_delete_message(SEIRawMessageList *list, int position)
Definition: cbs_sei.c:330
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
ff_cbs_sei_find_message
int ff_cbs_sei_find_message(CodedBitstreamContext *ctx, CodedBitstreamFragment *au, uint32_t payload_type, SEIRawMessage **iter)
Iterate over messages with the given payload type in an access unit.
Definition: cbs_sei.c:297
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:263
H264RawSEI
Definition: cbs_h264.h:305
AV_CODEC_ID_H265
#define AV_CODEC_ID_H265
Definition: codec_id.h:225
cbs_sei_get_unit
static int cbs_sei_get_unit(CodedBitstreamContext *ctx, CodedBitstreamFragment *au, int prefix, CodedBitstreamUnit **sei_unit)
Definition: cbs_sei.c:109
desc
const char * desc
Definition: libsvtav1.c:79
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
message
static int FUNC() message(CodedBitstreamContext *ctx, RWContext *rw, SEIRawMessage *current)
Definition: cbs_sei_syntax_template.c:147
ff_cbs_sei_list_add
int ff_cbs_sei_list_add(SEIRawMessageList *list)
Allocate a new empty SEI message in a message list.
Definition: cbs_sei.c:74
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
SEIRawUserDataUnregistered::data_ref
AVBufferRef * data_ref
Definition: cbs_sei.h:46
ff_cbs_sei_free_message_list
void ff_cbs_sei_free_message_list(SEIRawMessageList *list)
Free all SEI messages in a message list.
Definition: cbs_sei.c:99
HEVC_NAL_SEI_PREFIX
@ HEVC_NAL_SEI_PREFIX
Definition: hevc.h:68
CodedBitstreamFragment::nb_units
int nb_units
Number of units in this fragment.
Definition: cbs.h:152