FFmpeg  4.3
av1_frame_split_bsf.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 
21 /**
22  * @file
23  * This bitstream filter splits AV1 Temporal Units into packets containing
24  * just one frame, plus any leading and trailing OBUs that may be present at
25  * the beginning or end, respectively.
26  *
27  * Temporal Units already containing only one frame will be passed through
28  * unchanged. When splitting can't be performed, the Temporal Unit will be
29  * passed through containing only the remaining OBUs starting from the first
30  * one after the last successfully split frame.
31  */
32 
33 #include "libavutil/avassert.h"
34 
35 #include "bsf.h"
36 #include "bsf_internal.h"
37 #include "cbs.h"
38 #include "cbs_av1.h"
39 
40 typedef struct AV1FSplitContext {
44 
45  int nb_frames;
46  int cur_frame;
50 
52 {
55  int i, ret;
56  int split = !!s->buffer_pkt->data;
57 
58  if (!s->buffer_pkt->data) {
59  int nb_frames = 0;
60 
61  ret = ff_bsf_get_packet_ref(ctx, s->buffer_pkt);
62  if (ret < 0)
63  return ret;
64 
65  ret = ff_cbs_read_packet(s->cbc, td, s->buffer_pkt);
66  if (ret < 0) {
67  av_log(ctx, AV_LOG_WARNING, "Failed to parse temporal unit.\n");
68  goto passthrough;
69  }
70 
71  for (i = 0; i < td->nb_units; i++) {
72  CodedBitstreamUnit *unit = &td->units[i];
73 
74  if (unit->type == AV1_OBU_FRAME ||
75  unit->type == AV1_OBU_FRAME_HEADER)
76  nb_frames++;
77  else if (unit->type == AV1_OBU_TILE_LIST) {
78  av_log(ctx, AV_LOG_VERBOSE, "Large scale tiles are unsupported.\n");
79  goto passthrough;
80  }
81  }
82  if (nb_frames > 1) {
83  s->cur_frame = 0;
84  s->cur_frame_idx = s->last_frame_idx = 0;
85  s->nb_frames = nb_frames;
86  split = 1;
87  }
88  }
89 
90  if (split) {
92  int cur_frame_type = -1, size = 0;
93 
94  for (i = s->cur_frame_idx; i < td->nb_units; i++) {
95  CodedBitstreamUnit *unit = &td->units[i];
96 
97  size += unit->data_size;
98  if (unit->type == AV1_OBU_FRAME) {
99  AV1RawOBU *obu = unit->content;
100 
101  if (frame) {
102  av_log(ctx, AV_LOG_WARNING, "Frame OBU found when Tile data for a "
103  "previous frame was expected.\n");
104  goto passthrough;
105  }
106 
107  frame = &obu->obu.frame.header;
108  cur_frame_type = obu->header.obu_type;
110  s->cur_frame_idx = i + 1;
111  s->cur_frame++;
112 
113  // split here unless it's the last frame, in which case
114  // include every trailing OBU
115  if (s->cur_frame < s->nb_frames)
116  break;
117  } else if (unit->type == AV1_OBU_FRAME_HEADER) {
118  AV1RawOBU *obu = unit->content;
119 
120  if (frame) {
121  av_log(ctx, AV_LOG_WARNING, "Frame Header OBU found when Tile data for a "
122  "previous frame was expected.\n");
123  goto passthrough;
124  }
125 
126  frame = &obu->obu.frame_header;
127  cur_frame_type = obu->header.obu_type;
129  s->cur_frame++;
130 
131  // split here if show_existing_frame unless it's the last
132  // frame, in which case include every trailing OBU
133  if (frame->show_existing_frame &&
134  s->cur_frame < s->nb_frames) {
135  s->cur_frame_idx = i + 1;
136  break;
137  }
138  } else if (unit->type == AV1_OBU_TILE_GROUP) {
139  AV1RawOBU *obu = unit->content;
140  AV1RawTileGroup *group = &obu->obu.tile_group;
141 
142  if (!frame || cur_frame_type != AV1_OBU_FRAME_HEADER) {
143  av_log(ctx, AV_LOG_WARNING, "Unexpected Tile Group OBU found before a "
144  "Frame Header.\n");
145  goto passthrough;
146  }
147 
148  if ((group->tg_end == (frame->tile_cols * frame->tile_rows) - 1) &&
149  // include every trailing OBU with the last frame
150  s->cur_frame < s->nb_frames) {
151  s->cur_frame_idx = i + 1;
152  break;
153  }
154  }
155  }
156  av_assert0(frame && s->cur_frame <= s->nb_frames);
157 
158  ret = av_packet_ref(out, s->buffer_pkt);
159  if (ret < 0)
160  goto fail;
161 
162  out->data = (uint8_t *)td->units[s->last_frame_idx].data;
163  out->size = size;
164 
165  // skip the frame in the buffer packet if it's split successfully, so it's not present
166  // if the packet is passed through in case of failure when splitting another frame.
167  s->buffer_pkt->data += size;
168  s->buffer_pkt->size -= size;
169 
170  if (!frame->show_existing_frame && !frame->show_frame)
171  out->pts = AV_NOPTS_VALUE;
172 
173  if (s->cur_frame == s->nb_frames) {
175  ff_cbs_fragment_reset(s->cbc, td);
176  }
177 
178  return 0;
179  }
180 
181 passthrough:
183 
184  ret = 0;
185 fail:
186  if (ret < 0) {
187  av_packet_unref(out);
189  }
190  ff_cbs_fragment_reset(s->cbc, td);
191 
192  return ret;
193 }
194 
201 };
202 
204 {
205  AV1FSplitContext *s = ctx->priv_data;
207  int ret;
208 
210  if (!s->buffer_pkt)
211  return AVERROR(ENOMEM);
212 
213  ret = ff_cbs_init(&s->cbc, AV_CODEC_ID_AV1, ctx);
214  if (ret < 0)
215  return ret;
216 
219 
220  if (!ctx->par_in->extradata_size)
221  return 0;
222 
223  ret = ff_cbs_read_extradata(s->cbc, td, ctx->par_in);
224  if (ret < 0)
225  av_log(ctx, AV_LOG_WARNING, "Failed to parse extradata.\n");
226 
227  ff_cbs_fragment_reset(s->cbc, td);
228 
229  return 0;
230 }
231 
233 {
234  AV1FSplitContext *s = ctx->priv_data;
235 
238 }
239 
241 {
242  AV1FSplitContext *s = ctx->priv_data;
243 
246  ff_cbs_close(&s->cbc);
247 }
248 
249 static const enum AVCodecID av1_frame_split_codec_ids[] = {
251 };
252 
254  .name = "av1_frame_split",
255  .priv_data_size = sizeof(AV1FSplitContext),
258  .close = av1_frame_split_close,
261 };
#define NULL
Definition: coverity.c:32
int nb_units
Number of units in this fragment.
Definition: cbs.h:147
int size
if(ret< 0)
Definition: vf_mcdeint.c:279
static void flush(AVCodecContext *avctx)
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int ff_cbs_init(CodedBitstreamContext **ctx_ptr, enum AVCodecID codec_id, void *log_ctx)
Create and initialise a new context for the given codec.
Definition: cbs.c:74
CodedBitstreamUnitType type
Codec-specific type of this unit.
Definition: cbs.h:68
The bitstream filter state.
Definition: bsf.h:49
int size
Definition: packet.h:356
static void av1_frame_split_flush(AVBSFContext *ctx)
void * priv_data
Opaque filter-specific private data.
Definition: bsf.h:70
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
uint16_t tile_rows
Definition: cbs_av1.h:194
static void filter(int16_t *output, ptrdiff_t out_stride, int16_t *low, ptrdiff_t low_stride, int16_t *high, ptrdiff_t high_stride, int len, int clip)
Definition: cfhd.c:196
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: avpacket.c:64
uint8_t
uint32_t CodedBitstreamUnitType
The codec-specific type of a bitstream unit.
Definition: cbs.h:43
static AVFrame * frame
int ff_cbs_read_packet(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, const AVPacket *pkt)
Read the data bitstream from a packet into a fragment, then split into units and decompose.
Definition: cbs.c:242
const char * name
Definition: bsf.h:99
uint8_t * data
Definition: packet.h:355
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition: avpacket.c:663
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
Coded bitstream unit structure.
Definition: cbs.h:64
void * content
Pointer to the decomposed form of this unit.
Definition: cbs.h:101
CodedBitstreamUnit * units
Pointer to an array of units of length nb_units_allocated.
Definition: cbs.h:162
uint8_t * data
Pointer to the directly-parsable bitstream form of this unit.
Definition: cbs.h:75
#define av_log(a,...)
int av_packet_ref(AVPacket *dst, const AVPacket *src)
Setup a new reference to the data described by a given packet.
Definition: avpacket.c:614
void ff_cbs_fragment_free(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag)
Free the units array of a fragment in addition to what ff_cbs_fragment_reset does.
Definition: cbs.c:157
static const CodedBitstreamUnitType decompose_unit_types[]
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:46
#define td
Definition: regdef.h:70
#define AVERROR(e)
Definition: error.h:43
AV1RawFrame frame
Definition: cbs_av1.h:395
simple assert() macros that are a bit more flexible than ISO C assert().
union AV1RawOBU::@25 obu
#define fail()
Definition: checkasm.h:123
int extradata_size
Size of the extradata content in bytes.
Definition: codec_par.h:78
static char * split(char *message, char delim)
Definition: af_channelmap.c:81
CodedBitstreamContext * cbc
AV1RawOBUHeader header
Definition: cbs_av1.h:388
AVFormatContext * ctx
Definition: movenc.c:48
#define s(width, name)
Definition: cbs_vp9.c:257
#define FF_ARRAY_ELEMS(a)
static enum AVCodecID av1_frame_split_codec_ids[]
static int av1_frame_split_init(AVBSFContext *ctx)
int nb_decompose_unit_types
Length of the decompose_unit_types array.
Definition: cbs.h:201
Coded bitstream fragment structure, combining one or more units.
Definition: cbs.h:116
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:605
static void av1_frame_split_close(AVBSFContext *ctx)
void ff_cbs_fragment_reset(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag)
Free the units contained in a fragment as well as the fragment&#39;s own data buffer, but not the units a...
Definition: cbs.c:142
Context structure for coded bitstream operations.
Definition: cbs.h:168
uint8_t show_existing_frame
Definition: cbs_av1.h:134
void ff_cbs_close(CodedBitstreamContext **ctx_ptr)
Close a context and free all internal state.
Definition: cbs.c:115
uint8_t obu_type
Definition: cbs_av1.h:31
int ff_cbs_read_extradata(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, const AVCodecParameters *par)
Read the extradata bitstream found in codec parameters into a fragment, then split into units and dec...
Definition: cbs.c:224
uint16_t tile_cols
Definition: cbs_av1.h:193
const AVBitStreamFilter ff_av1_frame_split_bsf
static enum AVCodecID codec_ids[]
CodedBitstreamUnitType * decompose_unit_types
Array of unit types which should be decomposed when reading.
Definition: cbs.h:197
CodedBitstreamFragment temporal_unit
uint16_t tg_end
Definition: cbs_av1.h:294
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition: avpacket.c:53
AV1RawTileGroup tile_group
Definition: cbs_av1.h:396
AV1RawFrameHeader frame_header
Definition: cbs_av1.h:394
FILE * out
Definition: movenc.c:54
uint8_t show_frame
Definition: cbs_av1.h:140
AV1RawFrameHeader header
Definition: cbs_av1.h:300
static int av1_frame_split_filter(AVBSFContext *ctx, AVPacket *out)
This structure stores compressed data.
Definition: packet.h:332
AVCodecParameters * par_in
Parameters of the input stream.
Definition: bsf.h:77
int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt)
Called by bitstream filters to get packet for filtering.
Definition: bsf.c:249
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:348
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
size_t data_size
The number of bytes in the bitstream (including any padding bits in the final byte).
Definition: cbs.h:80