FFmpeg
evc_frame_merge.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 James Almer <jamrial@gmail.com>
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 #include "libavutil/mem.h"
21 #include "get_bits.h"
22 #include "bsf.h"
23 #include "bsf_internal.h"
24 
25 #include "evc.h"
26 #include "evc_parse.h"
27 #include "evc_ps.h"
28 
29 // Access unit data
30 typedef struct AccessUnitBuffer {
31  uint8_t *data; // the data buffer
32  size_t data_size; // size of data in bytes
33  unsigned capacity; // buffer capacity
35 
36 typedef struct EVCFMergeContext {
42 
44  const EVCParserPoc *poc, enum EVCNALUnitType nalu_type)
45 {
47  EVCParserSPS *sps = ps->sps[pps->pps_seq_parameter_set_id];
48 
49  av_assert0(sps && pps);
50 
51  if (sps->profile_idc == 0) { // BASELINE profile
52  if (nalu_type == EVC_NOIDR_NUT || nalu_type == EVC_IDR_NUT)
53  return 1;
54  } else { // MAIN profile
55  if (nalu_type == EVC_NOIDR_NUT) {
56  if (poc->PicOrderCntVal != poc->prevPicOrderCntVal)
57  return 1;
58  } else if (nalu_type == EVC_IDR_NUT)
59  return 1;
60  }
61  return 0;
62 }
63 
65 {
67 
68  ff_evc_ps_free(&ctx->ps);
69  av_packet_unref(ctx->in);
70  av_packet_unref(ctx->buffer_pkt);
71  ctx->au_buffer.data_size = 0;
72 }
73 
74 static int parse_nal_unit(AVBSFContext *bsf, const uint8_t *buf, int buf_size)
75 {
77  GetBitContext gb;
78  enum EVCNALUnitType nalu_type;
79  int tid, err;
80 
81  err = init_get_bits8(&gb, buf, buf_size);
82  if (err < 0)
83  return err;
84 
85  // @see ISO_IEC_23094-1_2020, 7.4.2.2 NAL unit header semantic (Table 4 - NAL unit type codes and NAL unit type classes)
86  // @see enum EVCNALUnitType in evc.h
87  if (get_bits1(&gb)) {// forbidden_zero_bit
88  av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit header\n");
89  return AVERROR_INVALIDDATA;
90  }
91 
92  nalu_type = get_bits(&gb, 6) - 1;
93  if (nalu_type < EVC_NOIDR_NUT || nalu_type > EVC_UNSPEC_NUT62) {
94  av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit type: (%d)\n", nalu_type);
95  return AVERROR_INVALIDDATA;
96  }
97 
98  tid = get_bits(&gb, 3);
99  skip_bits(&gb, 5); // nuh_reserved_zero_5bits
100  skip_bits1(&gb); // nuh_extension_flag
101 
102  switch (nalu_type) {
103  case EVC_SPS_NUT:
104  err = ff_evc_parse_sps(&gb, &ctx->ps);
105  if (err < 0) {
106  av_log(bsf, AV_LOG_ERROR, "SPS parsing error\n");
107  return err;
108  }
109  break;
110  case EVC_PPS_NUT:
111  err = ff_evc_parse_pps(&gb, &ctx->ps);
112  if (err < 0) {
113  av_log(bsf, AV_LOG_ERROR, "PPS parsing error\n");
114  return err;
115  }
116  break;
117  case EVC_IDR_NUT: // Coded slice of a IDR or non-IDR picture
118  case EVC_NOIDR_NUT: {
120 
121  err = ff_evc_parse_slice_header(&gb, &sh, &ctx->ps, nalu_type);
122  if (err < 0) {
123  av_log(bsf, AV_LOG_ERROR, "Slice header parsing error\n");
124  return err;
125  }
126 
127  // POC (picture order count of the current picture) derivation
128  // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count
129  err = ff_evc_derive_poc(&ctx->ps, &sh, &ctx->poc, nalu_type, tid);
130  if (err < 0)
131  return err;
132 
133  return end_of_access_unit_found(&ctx->ps, &sh, &ctx->poc, nalu_type);
134 
135  break;
136  }
137  case EVC_SEI_NUT: // Supplemental Enhancement Information
138  case EVC_APS_NUT: // Adaptation parameter set
139  case EVC_FD_NUT: // Filler data
140  default:
141  break;
142  }
143 
144  return 0;
145 }
146 
148 {
150  AVPacket *in = ctx->in, *buffer_pkt = ctx->buffer_pkt;
151  size_t data_size;
152  int au_end_found = 0, err;
153 
154  while (!au_end_found) {
155  uint8_t *buffer;
156  uint32_t nalu_size;
157 
158  if (!in->size) {
159  av_packet_unref(in);
160  err = ff_bsf_get_packet_ref(bsf, in);
161  if (err < 0) {
162  if (err == AVERROR_EOF && ctx->au_buffer.data_size > 0)
163  break;
164  return err;
165  }
166  /* Buffer packets with timestamps (there should be at most one per AU)
167  * or any packet if buffer_pkt is empty. The latter is needed to
168  * passthrough positions in case there are no timestamps like with
169  * the raw EVC demuxer. */
170  if (!buffer_pkt->data ||
171  in->pts != AV_NOPTS_VALUE && buffer_pkt->pts == AV_NOPTS_VALUE) {
172  err = av_packet_ref(buffer_pkt, in);
173  if (err < 0)
174  goto end;
175  }
176  }
177 
178  // Buffer size is not enough for buffer to store NAL unit 4-bytes prefix (length)
180  return AVERROR_INVALIDDATA;
181 
183  if (!nalu_size || nalu_size > INT_MAX) {
184  av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit size: (%u)\n", nalu_size);
185  err = AVERROR_INVALIDDATA;
186  goto end;
187  }
188 
189  if (in->size < nalu_size + EVC_NALU_LENGTH_PREFIX_SIZE) {
190  err = AVERROR_INVALIDDATA;
191  goto end;
192  }
193 
194  err = parse_nal_unit(bsf, in->data + EVC_NALU_LENGTH_PREFIX_SIZE, nalu_size);
195  if (err < 0) {
196  av_log(bsf, AV_LOG_ERROR, "Parsing of NAL unit failed\n");
197  goto end;
198  }
199  au_end_found = err;
200 
201  nalu_size += EVC_NALU_LENGTH_PREFIX_SIZE;
202 
203  data_size = ctx->au_buffer.data_size + nalu_size;
204  if (data_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
205  av_log(bsf, AV_LOG_ERROR, "Assembled packet is too big\n");
206  err = AVERROR(ERANGE);
207  goto end;
208  }
209 
210  buffer = av_fast_realloc(ctx->au_buffer.data, &ctx->au_buffer.capacity,
211  data_size);
212  if (!buffer) {
213  av_freep(&ctx->au_buffer.data);
214  err = AVERROR_INVALIDDATA;
215  goto end;
216  }
217 
218  ctx->au_buffer.data = buffer;
219  memcpy(ctx->au_buffer.data + ctx->au_buffer.data_size, in->data, nalu_size);
220 
221  ctx->au_buffer.data_size = data_size;
222 
223  in->data += nalu_size;
224  in->size -= nalu_size;
225  }
226 
227  av_packet_unref(in);
228  data_size = ctx->au_buffer.data_size;
229 
230  ctx->au_buffer.data_size = 0;
231  // drop the data in buffer_pkt, if any, but keep the props
232  av_buffer_unref(&buffer_pkt->buf);
233  err = av_buffer_realloc(&buffer_pkt->buf, data_size + AV_INPUT_BUFFER_PADDING_SIZE);
234  if (err < 0)
235  goto end;
236 
237  buffer_pkt->data = buffer_pkt->buf->data;
238  buffer_pkt->size = data_size;
239  av_packet_move_ref(out, buffer_pkt);
240  memcpy(out->data, ctx->au_buffer.data, data_size);
241  memset(out->data + data_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
242 
243  err = 0;
244 end:
245  if (err < 0) {
246  av_packet_unref(in);
247  av_packet_unref(buffer_pkt);
248  ctx->au_buffer.data_size = 0;
249  }
250  return err;
251 }
252 
254 {
256 
257  ctx->in = av_packet_alloc();
258  ctx->buffer_pkt = av_packet_alloc();
259  if (!ctx->in || !ctx->buffer_pkt)
260  return AVERROR(ENOMEM);
261 
262  return 0;
263 }
264 
266 {
268 
269  av_packet_free(&ctx->in);
270  av_packet_free(&ctx->buffer_pkt);
271  ff_evc_ps_free(&ctx->ps);
272 
273  ctx->au_buffer.capacity = 0;
274  av_freep(&ctx->au_buffer.data);
275  ctx->au_buffer.data_size = 0;
276 }
277 
278 static const enum AVCodecID evc_frame_merge_codec_ids[] = {
280 };
281 
283  .p.name = "evc_frame_merge",
284  .p.codec_ids = evc_frame_merge_codec_ids,
285  .priv_data_size = sizeof(EVCFMergeContext),
288  .close = evc_frame_merge_close,
290 };
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: packet.c:427
EVCParserPoc::PicOrderCntVal
int PicOrderCntVal
Definition: evc_parse.h:78
ff_evc_parse_pps
int ff_evc_parse_pps(GetBitContext *gb, EVCParamSets *ps)
Definition: evc_ps.c:352
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
bsf_internal.h
EVC_APS_NUT
@ EVC_APS_NUT
Definition: evc.h:60
out
FILE * out
Definition: movenc.c:55
evc_frame_merge_codec_ids
static enum AVCodecID evc_frame_merge_codec_ids[]
Definition: evc_frame_merge.c:278
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
evc_parse.h
EVCFMergeContext::au_buffer
AccessUnitBuffer au_buffer
Definition: evc_frame_merge.c:40
AVBitStreamFilter::name
const char * name
Definition: bsf.h:112
ff_evc_frame_merge_bsf
const FFBitStreamFilter ff_evc_frame_merge_bsf
Definition: evc_frame_merge.c:282
AccessUnitBuffer
Definition: evc_frame_merge.c:30
AVPacket::data
uint8_t * data
Definition: packet.h:524
EVCParamSets
Definition: evc_ps.h:211
filter
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce then the filter should push the output frames on the output link immediately As an exception to the previous rule if the input frame is enough to produce several output frames then the filter needs output only at least one per link The additional frames can be left buffered in the filter
Definition: filter_design.txt:228
evc_frame_merge_init
static int evc_frame_merge_init(AVBSFContext *bsf)
Definition: evc_frame_merge.c:253
av_packet_free
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: packet.c:74
AVBSFContext
The bitstream filter state.
Definition: bsf.h:68
evc_ps.h
EVC_IDR_NUT
@ EVC_IDR_NUT
Definition: evc.h:35
skip_bits
static void skip_bits(GetBitContext *s, int n)
Definition: get_bits.h:381
EVCParamSets::pps
EVCParserPPS * pps[EVC_MAX_PPS_COUNT]
Definition: evc_ps.h:213
get_bits
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:335
EVC_NOIDR_NUT
@ EVC_NOIDR_NUT
Definition: evc.h:34
bsf.h
GetBitContext
Definition: get_bits.h:108
EVC_SEI_NUT
@ EVC_SEI_NUT
Definition: evc.h:62
evc_frame_merge_close
static void evc_frame_merge_close(AVBSFContext *bsf)
Definition: evc_frame_merge.c:265
ff_evc_ps_free
void ff_evc_ps_free(EVCParamSets *ps)
Definition: evc_ps.c:437
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
ff_evc_parse_sps
int ff_evc_parse_sps(GetBitContext *gb, EVCParamSets *ps)
Definition: evc_ps.c:152
init_get_bits8
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition: get_bits.h:545
av_fast_realloc
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
Definition: mem.c:497
ff_evc_parse_slice_header
int ff_evc_parse_slice_header(GetBitContext *gb, EVCParserSliceHeader *sh, const EVCParamSets *ps, enum EVCNALUnitType nalu_type)
Definition: evc_parse.c:24
AV_CODEC_ID_EVC
@ AV_CODEC_ID_EVC
Definition: codec_id.h:321
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
ctx
AVFormatContext * ctx
Definition: movenc.c:49
get_bits.h
EVCFMergeContext::in
AVPacket * in
Definition: evc_frame_merge.c:37
FFBitStreamFilter
Definition: bsf_internal.h:27
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
EVCFMergeContext
Definition: evc_frame_merge.c:36
get_bits1
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:388
flush
void(* flush)(AVBSFContext *ctx)
Definition: dts2pts.c:368
av_packet_ref
int av_packet_ref(AVPacket *dst, const AVPacket *src)
Setup a new reference to the data described by a given packet.
Definition: packet.c:435
av_packet_move_ref
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition: packet.c:484
AVCodecID
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:49
FFBitStreamFilter::p
AVBitStreamFilter p
The public AVBitStreamFilter.
Definition: bsf_internal.h:31
EVCParserSliceHeader::slice_pic_parameter_set_id
uint8_t slice_pic_parameter_set_id
Definition: evc_parse.h:43
parse_nal_unit
static int parse_nal_unit(AVBSFContext *bsf, const uint8_t *buf, int buf_size)
Definition: evc_frame_merge.c:74
EVCParamSets::sps
EVCParserSPS * sps[EVC_MAX_SPS_COUNT]
Definition: evc_ps.h:212
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:366
AVPacket::size
int size
Definition: packet.h:525
end_of_access_unit_found
static int end_of_access_unit_found(const EVCParamSets *ps, const EVCParserSliceHeader *sh, const EVCParserPoc *poc, enum EVCNALUnitType nalu_type)
Definition: evc_frame_merge.c:43
EVCParserSliceHeader
Definition: evc_parse.h:42
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
EVCNALUnitType
EVCNALUnitType
Definition: evc.h:33
EVCFMergeContext::poc
EVCParserPoc poc
Definition: evc_frame_merge.c:39
skip_bits1
static void skip_bits1(GetBitContext *s)
Definition: get_bits.h:413
av_packet_alloc
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition: packet.c:63
EVC_FD_NUT
@ EVC_FD_NUT
Definition: evc.h:61
EVC_NALU_LENGTH_PREFIX_SIZE
#define EVC_NALU_LENGTH_PREFIX_SIZE
Definition: evc.h:26
AccessUnitBuffer::data
uint8_t * data
Definition: evc_frame_merge.c:31
AV_CODEC_ID_NONE
@ AV_CODEC_ID_NONE
Definition: codec_id.h:50
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:517
AccessUnitBuffer::data_size
size_t data_size
Definition: evc_frame_merge.c:32
EVC_PPS_NUT
@ EVC_PPS_NUT
Definition: evc.h:59
evc_frame_merge_flush
static void evc_frame_merge_flush(AVBSFContext *bsf)
Definition: evc_frame_merge.c:64
EVC_UNSPEC_NUT62
@ EVC_UNSPEC_NUT62
Definition: evc.h:96
AVBSFContext::priv_data
void * priv_data
Opaque filter-specific private data.
Definition: bsf.h:83
sps
static int FUNC() sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
Definition: cbs_h264_syntax_template.c:260
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
EVCFMergeContext::buffer_pkt
AVPacket * buffer_pkt
Definition: evc_frame_merge.c:37
EVCParserPoc::prevPicOrderCntVal
int prevPicOrderCntVal
Definition: evc_parse.h:79
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
evc_read_nal_unit_length
static uint32_t evc_read_nal_unit_length(const uint8_t *bits, int bits_size, void *logctx)
Definition: evc_parse.h:83
AccessUnitBuffer::capacity
unsigned capacity
Definition: evc_frame_merge.c:33
pps
uint64_t pps
Definition: dovi_rpuenc.c:35
av_buffer_realloc
int av_buffer_realloc(AVBufferRef **pbuf, size_t size)
Reallocate a given buffer.
Definition: buffer.c:183
EVC_SPS_NUT
@ EVC_SPS_NUT
Definition: evc.h:58
EVCParserSPS
Definition: evc_ps.h:111
mem.h
EVCFMergeContext::ps
EVCParamSets ps
Definition: evc_frame_merge.c:38
EVCParserPPS
Definition: evc_ps.h:185
EVCParserPoc
Definition: evc_parse.h:77
AVPacket
This structure stores compressed data.
Definition: packet.h:501
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
ff_bsf_get_packet_ref
int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt)
Called by bitstream filters to get packet for filtering.
Definition: bsf.c:256
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
evc_frame_merge_filter
static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out)
Definition: evc_frame_merge.c:147
ff_evc_derive_poc
int ff_evc_derive_poc(const EVCParamSets *ps, const EVCParserSliceHeader *sh, EVCParserPoc *poc, enum EVCNALUnitType nalu_type, int tid)
Definition: evc_parse.c:140