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 "get_bits.h"
21 #include "bsf.h"
22 #include "bsf_internal.h"
23 
24 #include "evc.h"
25 #include "evc_parse.h"
26 #include "evc_ps.h"
27 
28 // Access unit data
29 typedef struct AccessUnitBuffer {
30  uint8_t *data; // the data buffer
31  size_t data_size; // size of data in bytes
32  unsigned capacity; // buffer capacity
34 
35 typedef struct EVCFMergeContext {
41 
43  const EVCParserPoc *poc, enum EVCNALUnitType nalu_type)
44 {
46  EVCParserSPS *sps = ps->sps[pps->pps_seq_parameter_set_id];
47 
48  av_assert0(sps && pps);
49 
50  if (sps->profile_idc == 0) { // BASELINE profile
51  if (nalu_type == EVC_NOIDR_NUT || nalu_type == EVC_IDR_NUT)
52  return 1;
53  } else { // MAIN profile
54  if (nalu_type == EVC_NOIDR_NUT) {
55  if (poc->PicOrderCntVal != poc->prevPicOrderCntVal)
56  return 1;
57  } else if (nalu_type == EVC_IDR_NUT)
58  return 1;
59  }
60  return 0;
61 }
62 
64 {
66 
67  ff_evc_ps_free(&ctx->ps);
68  av_packet_unref(ctx->in);
69  av_packet_unref(ctx->buffer_pkt);
70  ctx->au_buffer.data_size = 0;
71 }
72 
73 static int parse_nal_unit(AVBSFContext *bsf, const uint8_t *buf, int buf_size)
74 {
76  GetBitContext gb;
77  enum EVCNALUnitType nalu_type;
78  int tid, err;
79 
80  err = init_get_bits8(&gb, buf, buf_size);
81  if (err < 0)
82  return err;
83 
84  // @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)
85  // @see enum EVCNALUnitType in evc.h
86  if (get_bits1(&gb)) {// forbidden_zero_bit
87  av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit header\n");
88  return AVERROR_INVALIDDATA;
89  }
90 
91  nalu_type = get_bits(&gb, 6) - 1;
92  if (nalu_type < EVC_NOIDR_NUT || nalu_type > EVC_UNSPEC_NUT62) {
93  av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit type: (%d)\n", nalu_type);
94  return AVERROR_INVALIDDATA;
95  }
96 
97  tid = get_bits(&gb, 3);
98  skip_bits(&gb, 5); // nuh_reserved_zero_5bits
99  skip_bits1(&gb); // nuh_extension_flag
100 
101  switch (nalu_type) {
102  case EVC_SPS_NUT:
103  err = ff_evc_parse_sps(&gb, &ctx->ps);
104  if (err < 0) {
105  av_log(bsf, AV_LOG_ERROR, "SPS parsing error\n");
106  return err;
107  }
108  break;
109  case EVC_PPS_NUT:
110  err = ff_evc_parse_pps(&gb, &ctx->ps);
111  if (err < 0) {
112  av_log(bsf, AV_LOG_ERROR, "PPS parsing error\n");
113  return err;
114  }
115  break;
116  case EVC_IDR_NUT: // Coded slice of a IDR or non-IDR picture
117  case EVC_NOIDR_NUT: {
119 
120  err = ff_evc_parse_slice_header(&gb, &sh, &ctx->ps, nalu_type);
121  if (err < 0) {
122  av_log(bsf, AV_LOG_ERROR, "Slice header parsing error\n");
123  return err;
124  }
125 
126  // POC (picture order count of the current picture) derivation
127  // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count
128  err = ff_evc_derive_poc(&ctx->ps, &sh, &ctx->poc, nalu_type, tid);
129  if (err < 0)
130  return err;
131 
132  return end_of_access_unit_found(&ctx->ps, &sh, &ctx->poc, nalu_type);
133 
134  break;
135  }
136  case EVC_SEI_NUT: // Supplemental Enhancement Information
137  case EVC_APS_NUT: // Adaptation parameter set
138  case EVC_FD_NUT: // Filler data
139  default:
140  break;
141  }
142 
143  return 0;
144 }
145 
147 {
149  AVPacket *in = ctx->in, *buffer_pkt = ctx->buffer_pkt;
150  size_t data_size;
151  int au_end_found = 0, err;
152 
153  while (!au_end_found) {
154  uint8_t *buffer;
155  uint32_t nalu_size;
156 
157  if (!in->size) {
158  av_packet_unref(in);
159  err = ff_bsf_get_packet_ref(bsf, in);
160  if (err < 0) {
161  if (err == AVERROR_EOF && ctx->au_buffer.data_size > 0)
162  break;
163  return err;
164  }
165  /* Buffer packets with timestamps (there should be at most one per AU)
166  * or any packet if buffer_pkt is empty. The latter is needed to
167  * passthrough positions in case there are no timestamps like with
168  * the raw EVC demuxer. */
169  if (!buffer_pkt->data ||
170  in->pts != AV_NOPTS_VALUE && buffer_pkt->pts == AV_NOPTS_VALUE) {
171  err = av_packet_ref(buffer_pkt, in);
172  if (err < 0)
173  goto end;
174  }
175  }
176 
177  // Buffer size is not enough for buffer to store NAL unit 4-bytes prefix (length)
179  return AVERROR_INVALIDDATA;
180 
182  if (!nalu_size || nalu_size > INT_MAX) {
183  av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit size: (%u)\n", nalu_size);
184  err = AVERROR_INVALIDDATA;
185  goto end;
186  }
187 
188  if (in->size < nalu_size + EVC_NALU_LENGTH_PREFIX_SIZE) {
189  err = AVERROR_INVALIDDATA;
190  goto end;
191  }
192 
193  err = parse_nal_unit(bsf, in->data + EVC_NALU_LENGTH_PREFIX_SIZE, nalu_size);
194  if (err < 0) {
195  av_log(bsf, AV_LOG_ERROR, "Parsing of NAL unit failed\n");
196  goto end;
197  }
198  au_end_found = err;
199 
200  nalu_size += EVC_NALU_LENGTH_PREFIX_SIZE;
201 
202  data_size = ctx->au_buffer.data_size + nalu_size;
203  if (data_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
204  av_log(bsf, AV_LOG_ERROR, "Assembled packet is too big\n");
205  err = AVERROR(ERANGE);
206  goto end;
207  }
208 
209  buffer = av_fast_realloc(ctx->au_buffer.data, &ctx->au_buffer.capacity,
210  data_size);
211  if (!buffer) {
212  av_freep(&ctx->au_buffer.data);
213  err = AVERROR_INVALIDDATA;
214  goto end;
215  }
216 
217  ctx->au_buffer.data = buffer;
218  memcpy(ctx->au_buffer.data + ctx->au_buffer.data_size, in->data, nalu_size);
219 
220  ctx->au_buffer.data_size = data_size;
221 
222  in->data += nalu_size;
223  in->size -= nalu_size;
224  }
225 
226  av_packet_unref(in);
227  data_size = ctx->au_buffer.data_size;
228 
229  ctx->au_buffer.data_size = 0;
230  // drop the data in buffer_pkt, if any, but keep the props
231  av_buffer_unref(&buffer_pkt->buf);
232  err = av_buffer_realloc(&buffer_pkt->buf, data_size + AV_INPUT_BUFFER_PADDING_SIZE);
233  if (err < 0)
234  goto end;
235 
236  buffer_pkt->data = buffer_pkt->buf->data;
237  buffer_pkt->size = data_size;
238  av_packet_move_ref(out, buffer_pkt);
239  memcpy(out->data, ctx->au_buffer.data, data_size);
240  memset(out->data + data_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
241 
242  err = 0;
243 end:
244  if (err < 0) {
245  av_packet_unref(in);
246  av_packet_unref(buffer_pkt);
247  ctx->au_buffer.data_size = 0;
248  }
249  return err;
250 }
251 
253 {
255 
256  ctx->in = av_packet_alloc();
257  ctx->buffer_pkt = av_packet_alloc();
258  if (!ctx->in || !ctx->buffer_pkt)
259  return AVERROR(ENOMEM);
260 
261  return 0;
262 }
263 
265 {
267 
268  av_packet_free(&ctx->in);
269  av_packet_free(&ctx->buffer_pkt);
270  ff_evc_ps_free(&ctx->ps);
271 
272  ctx->au_buffer.capacity = 0;
273  av_freep(&ctx->au_buffer.data);
274  ctx->au_buffer.data_size = 0;
275 }
276 
277 static const enum AVCodecID evc_frame_merge_codec_ids[] = {
279 };
280 
282  .p.name = "evc_frame_merge",
283  .p.codec_ids = evc_frame_merge_codec_ids,
284  .priv_data_size = sizeof(EVCFMergeContext),
287  .close = evc_frame_merge_close,
289 };
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.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:351
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:54
evc_frame_merge_codec_ids
static enum AVCodecID evc_frame_merge_codec_ids[]
Definition: evc_frame_merge.c:277
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:39
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:281
AccessUnitBuffer
Definition: evc_frame_merge.c:29
AVPacket::data
uint8_t * data
Definition: packet.h:522
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:252
av_packet_free
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: avpacket.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:264
ff_evc_ps_free
void ff_evc_ps_free(EVCParamSets *ps)
Definition: evc_ps.c:436
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:151
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:495
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:48
get_bits.h
EVCFMergeContext::in
AVPacket * in
Definition: evc_frame_merge.c:36
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:35
get_bits1
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:388
flush
void(* flush)(AVBSFContext *ctx)
Definition: dts2pts.c:367
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: avpacket.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: avpacket.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:73
EVCParamSets::sps
EVCParserSPS * sps[EVC_MAX_SPS_COUNT]
Definition: evc_ps.h:212
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:365
AVPacket::size
int size
Definition: packet.h:523
pps
static int FUNC() pps(CodedBitstreamContext *ctx, RWContext *rw, H264RawPPS *current)
Definition: cbs_h264_syntax_template.c:404
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:42
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:38
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: avpacket.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:30
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:515
AccessUnitBuffer::data_size
size_t data_size
Definition: evc_frame_merge.c:31
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:63
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:36
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:32
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
EVCFMergeContext::ps
EVCParamSets ps
Definition: evc_frame_merge.c:37
EVCParserPPS
Definition: evc_ps.h:185
EVCParserPoc
Definition: evc_parse.h:77
AVPacket
This structure stores compressed data.
Definition: packet.h:499
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:146
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