FFmpeg
evcdec.c
Go to the documentation of this file.
1 /*
2  * RAW EVC video demuxer
3  *
4  * Copyright (c) 2021 Dawid Kozinski <d.kozinski@samsung.com>
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include "libavcodec/evc.h"
24 #include "libavcodec/bsf.h"
25 
26 #include "libavutil/opt.h"
27 
28 #include "avformat.h"
29 #include "avio_internal.h"
30 #include "demux.h"
31 #include "evc.h"
32 #include "internal.h"
33 
34 
35 #define RAW_PACKET_SIZE 1024
36 
37 typedef struct EVCDemuxContext {
38  const AVClass *class;
40 
42 
44 
45 #define DEC AV_OPT_FLAG_DECODING_PARAM
46 #define OFFSET(x) offsetof(EVCDemuxContext, x)
47 static const AVOption evc_options[] = {
48  { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC},
49  { NULL },
50 };
51 #undef OFFSET
52 
53 static const AVClass evc_demuxer_class = {
54  .class_name = "EVC Annex B demuxer",
55  .item_name = av_default_item_name,
56  .option = evc_options,
57  .version = LIBAVUTIL_VERSION_INT,
58 };
59 
60 static int annexb_probe(const AVProbeData *p)
61 {
62  int nalu_type;
63  size_t nalu_size;
64  int got_sps = 0, got_pps = 0, got_idr = 0, got_nonidr = 0;
65  const unsigned char *bits = p->buf;
66  int bytes_to_read = p->buf_size;
67 
68  while (bytes_to_read > EVC_NALU_LENGTH_PREFIX_SIZE) {
69 
71  if (nalu_size == 0) break;
72 
74  bytes_to_read -= EVC_NALU_LENGTH_PREFIX_SIZE;
75 
76  if(bytes_to_read < nalu_size) break;
77 
78  nalu_type = evc_get_nalu_type(bits, bytes_to_read);
79 
80  if (nalu_type == EVC_SPS_NUT)
81  got_sps++;
82  else if (nalu_type == EVC_PPS_NUT)
83  got_pps++;
84  else if (nalu_type == EVC_IDR_NUT )
85  got_idr++;
86  else if (nalu_type == EVC_NOIDR_NUT)
87  got_nonidr++;
88 
89  bits += nalu_size;
90  bytes_to_read -= nalu_size;
91  }
92 
93  if (got_sps && got_pps && (got_idr || got_nonidr > 3))
94  return AVPROBE_SCORE_EXTENSION + 1; // 1 more than .mpg
95 
96  return 0;
97 }
98 
100 {
101  AVStream *st;
102  FFStream *sti;
103  const AVBitStreamFilter *filter = av_bsf_get_by_name("evc_frame_merge");
104  EVCDemuxContext *c = s->priv_data;
105  int ret = 0;
106 
107  st = avformat_new_stream(s, NULL);
108  if (!st) {
109  ret = AVERROR(ENOMEM);
110  goto fail;
111  }
112  sti = ffstream(st);
113 
116 
117  // This causes sending to the parser full frames, not chunks of data
118  // The flag PARSER_FLAG_COMPLETE_FRAMES will be set in demux.c (demux.c: 1316)
120 
121  st->avg_frame_rate = c->framerate;
122 
123  // taken from rawvideo demuxers
124  avpriv_set_pts_info(st, 64, 1, 1200000);
125 
126  ret = av_bsf_alloc(filter, &c->bsf);
127  if (ret < 0)
128  return ret;
129 
130  ret = avcodec_parameters_copy(c->bsf->par_in, st->codecpar);
131  if (ret < 0)
132  return ret;
133 
134  ret = av_bsf_init(c->bsf);
135  if (ret < 0)
136  return ret;
137 
138 fail:
139  return ret;
140 }
141 
143 {
144  int ret;
145  uint32_t nalu_size;
146  int au_end_found = 0;
147  EVCDemuxContext *const c = s->priv_data;
148 
149  while(!au_end_found) {
150  uint8_t buf[EVC_NALU_LENGTH_PREFIX_SIZE];
151 
152  if (avio_feof(s->pb))
153  goto end;
154 
156  if (ret < 0)
157  return ret;
158 
160  if (ret < 0)
161  return ret;
163  return AVERROR_INVALIDDATA;
164 
166  if (!nalu_size || nalu_size > INT_MAX)
167  return AVERROR_INVALIDDATA;
168 
169  avio_seek(s->pb, -EVC_NALU_LENGTH_PREFIX_SIZE, SEEK_CUR);
170 
171  ret = av_get_packet(s->pb, pkt, nalu_size + EVC_NALU_LENGTH_PREFIX_SIZE);
172  if (ret < 0)
173  return ret;
174  if (ret != (nalu_size + EVC_NALU_LENGTH_PREFIX_SIZE))
175  return AVERROR_INVALIDDATA;
176 
177 end:
178  ret = av_bsf_send_packet(c->bsf, pkt);
179  if (ret < 0) {
180  av_log(s, AV_LOG_ERROR, "Failed to send packet to "
181  "evc_frame_merge filter\n");
182  return ret;
183  }
184 
185  ret = av_bsf_receive_packet(c->bsf, pkt);
186  if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
187  av_log(s, AV_LOG_ERROR, "evc_frame_merge filter failed to "
188  "send output packet\n");
189 
190  if (ret != AVERROR(EAGAIN))
191  au_end_found = 1;
192  }
193 
194  return ret;
195 }
196 
198 {
199  EVCDemuxContext *const c = s->priv_data;
200 
201  av_bsf_free(&c->bsf);
202  return 0;
203 }
204 
206  .p.name = "evc",
207  .p.long_name = NULL_IF_CONFIG_SMALL("EVC Annex B"),
208  .p.extensions = "evc",
210  .p.priv_class = &evc_demuxer_class,
211  .read_probe = annexb_probe,
212  .read_header = evc_read_header, // annexb_read_header
213  .read_packet = evc_read_packet, // annexb_read_packet
214  .read_close = evc_read_close,
215  .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
216  .raw_codec_id = AV_CODEC_ID_EVC,
217  .priv_data_size = sizeof(EVCDemuxContext),
218 };
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
opt.h
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:51
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
AV_OPT_TYPE_VIDEO_RATE
@ AV_OPT_TYPE_VIDEO_RATE
offset must point to AVRational
Definition: opt.h:248
AVFMT_NOTIMESTAMPS
#define AVFMT_NOTIMESTAMPS
Format does not need / have any timestamps.
Definition: avformat.h:479
AVOption
AVOption.
Definition: opt.h:346
AVStream::avg_frame_rate
AVRational avg_frame_rate
Average framerate.
Definition: avformat.h:832
evc_get_nalu_type
static int evc_get_nalu_type(const uint8_t *p, int bits_size)
Definition: evc.h:32
EVCDemuxContext::framerate
AVRational framerate
Definition: evcdec.c:39
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
AVProbeData::buf_size
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:454
av_bsf_free
void av_bsf_free(AVBSFContext **pctx)
Free a bitstream filter context and everything associated with it; write NULL into the supplied point...
Definition: bsf.c:52
ff_evc_demuxer
const FFInputFormat ff_evc_demuxer
Definition: evcdec.c:205
AVBSFContext
The bitstream filter state.
Definition: bsf.h:68
evc_demuxer_class
static const AVClass evc_demuxer_class
Definition: evcdec.c:53
EVC_IDR_NUT
@ EVC_IDR_NUT
Definition: evc.h:35
EVC_NOIDR_NUT
@ EVC_NOIDR_NUT
Definition: evc.h:34
avpriv_set_pts_info
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: avformat.c:853
bsf.h
evc_options
static const AVOption evc_options[]
Definition: evcdec.c:47
ffstream
static av_always_inline FFStream * ffstream(AVStream *st)
Definition: internal.h:417
fail
#define fail()
Definition: checkasm.h:179
AVFMT_GENERIC_INDEX
#define AVFMT_GENERIC_INDEX
Use generic index building code.
Definition: avformat.h:480
annexb_probe
static int annexb_probe(const AVProbeData *p)
Definition: evcdec.c:60
pkt
AVPacket * pkt
Definition: movenc.c:60
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
evc_read_packet
static int evc_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: evcdec.c:142
evc_read_header
static int evc_read_header(AVFormatContext *s)
Definition: evcdec.c:99
s
#define s(width, name)
Definition: cbs_vp9.c:198
AV_CODEC_ID_EVC
@ AV_CODEC_ID_EVC
Definition: codec_id.h:321
DEC
#define DEC
Definition: evcdec.c:45
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:553
AVProbeData::buf
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:453
bits
uint8_t bits
Definition: vp3data.h:128
av_bsf_alloc
int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **pctx)
Allocate a context for a given bitstream filter.
Definition: bsf.c:104
FF_INFMT_FLAG_INIT_CLEANUP
#define FF_INFMT_FLAG_INIT_CLEANUP
For an FFInputFormat with this flag set read_close() needs to be called by the caller upon read_heade...
Definition: demux.h:35
FFStream::need_parsing
enum AVStreamParseType need_parsing
Definition: internal.h:386
AVFormatContext
Format I/O context.
Definition: avformat.h:1255
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:766
framerate
float framerate
Definition: av1_levels.c:29
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
av_bsf_init
int av_bsf_init(AVBSFContext *ctx)
Prepare the filter for use, after all the parameters and options have been set.
Definition: bsf.c:149
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
OFFSET
#define OFFSET(x)
Definition: evcdec.c:46
av_bsf_receive_packet
int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt)
Retrieve a filtered packet.
Definition: bsf.c:230
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
AVProbeData
This structure contains the data a format has to probe a file.
Definition: avformat.h:451
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
AVPROBE_SCORE_EXTENSION
#define AVPROBE_SCORE_EXTENSION
score for file extension
Definition: avformat.h:461
evc_read_close
static int evc_read_close(AVFormatContext *s)
Definition: evcdec.c:197
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:94
FFStream
Definition: internal.h:193
av_bsf_send_packet
int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt)
Submit a packet for filtering.
Definition: bsf.c:202
FFInputFormat::p
AVInputFormat p
The public AVInputFormat.
Definition: demux.h:41
EVCDemuxContext
Definition: evcdec.c:37
ffio_ensure_seekback
int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size)
Ensures that the requested seekback buffer size will be available.
Definition: aviobuf.c:1023
EVC_NALU_LENGTH_PREFIX_SIZE
#define EVC_NALU_LENGTH_PREFIX_SIZE
Definition: evc.h:26
avio_internal.h
demux.h
EVC_PPS_NUT
@ EVC_PPS_NUT
Definition: evc.h:59
av_get_packet
int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
Allocate and read the payload of a packet and initialize its fields with default values.
Definition: utils.c:104
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:743
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:231
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:71
AVSTREAM_PARSE_HEADERS
@ AVSTREAM_PARSE_HEADERS
Only parse headers, do not repack.
Definition: avformat.h:594
avformat.h
AVBitStreamFilter
Definition: bsf.h:111
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
avio_read
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:612
EVC_SPS_NUT
@ EVC_SPS_NUT
Definition: evc.h:58
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
EVCDemuxContext::bsf
AVBSFContext * bsf
Definition: evcdec.c:41
evc.h
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:55
AVPacket
This structure stores compressed data.
Definition: packet.h:501
FFInputFormat
Definition: demux.h:37
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
avcodec_parameters_copy
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: codec_par.c:106
avio_feof
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition: aviobuf.c:346
av_bsf_get_by_name
const AVBitStreamFilter * av_bsf_get_by_name(const char *name)
Definition: bitstream_filters.c:86