FFmpeg  4.4
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 {
54  CodedBitstreamFragment *td = &s->temporal_unit;
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;
109  s->last_frame_idx = s->cur_frame_idx;
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;
128  s->last_frame_idx = s->cur_frame_idx;
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) {
174  av_packet_unref(s->buffer_pkt);
176  }
177 
178  return 0;
179  }
180 
181 passthrough:
182  av_packet_move_ref(out, s->buffer_pkt);
183 
184  ret = 0;
185 fail:
186  if (ret < 0) {
188  av_packet_unref(s->buffer_pkt);
189  }
191 
192  return ret;
193 }
194 
201 };
202 
204 {
206  CodedBitstreamFragment *td = &s->temporal_unit;
207  int ret;
208 
209  s->buffer_pkt = av_packet_alloc();
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 
217  s->cbc->decompose_unit_types = decompose_unit_types;
218  s->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(decompose_unit_types);
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 
228 
229  return 0;
230 }
231 
233 {
235 
236  av_packet_unref(s->buffer_pkt);
237  ff_cbs_fragment_reset(&s->temporal_unit);
238 }
239 
241 {
243 
244  av_packet_free(&s->buffer_pkt);
245  ff_cbs_fragment_free(&s->temporal_unit);
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 };
static enum AVCodecID codec_ids[]
static void flush(AVCodecContext *avctx)
static char * split(char *message, char delim)
Definition: af_channelmap.c:81
uint8_t
static void av1_frame_split_close(AVBSFContext *ctx)
static enum AVCodecID av1_frame_split_codec_ids[]
static const CodedBitstreamUnitType decompose_unit_types[]
static int av1_frame_split_init(AVBSFContext *ctx)
static int av1_frame_split_filter(AVBSFContext *ctx, AVPacket *out)
static void av1_frame_split_flush(AVBSFContext *ctx)
const AVBitStreamFilter ff_av1_frame_split_bsf
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:31
int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt)
Called by bitstream filters to get packet for filtering.
Definition: bsf.c:253
void ff_cbs_close(CodedBitstreamContext **ctx_ptr)
Close a context and free all internal state.
Definition: cbs.c:126
void ff_cbs_fragment_reset(CodedBitstreamFragment *frag)
Free the units contained in a fragment as well as the fragment's own data buffer, but not the units a...
Definition: cbs.c:156
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:288
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:270
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:75
void ff_cbs_fragment_free(CodedBitstreamFragment *frag)
Free the units array of a fragment in addition to what ff_cbs_fragment_reset does.
Definition: cbs.c:170
uint32_t CodedBitstreamUnitType
The codec-specific type of a bitstream unit.
Definition: cbs.h:43
#define s(width, name)
Definition: cbs_vp9.c:257
static av_always_inline void filter(int16_t *output, ptrdiff_t out_stride, const int16_t *low, ptrdiff_t low_stride, const int16_t *high, ptrdiff_t high_stride, int len, int clip)
Definition: cfhddsp.c:27
#define fail()
Definition: checkasm.h:133
#define NULL
Definition: coverity.c:32
static AVFrame * frame
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:46
@ AV_CODEC_ID_NONE
Definition: codec_id.h:47
@ AV_CODEC_ID_AV1
Definition: codec_id.h:279
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: avpacket.c:75
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:634
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition: avpacket.c:690
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition: avpacket.c:64
int av_packet_ref(AVPacket *dst, const AVPacket *src)
Setup a new reference to the data described by a given packet.
Definition: avpacket.c:641
#define AVERROR(e)
Definition: error.h:43
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:210
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
int i
Definition: input.c:407
@ AV1_OBU_TILE_LIST
Definition: av1.h:37
@ AV1_OBU_TEMPORAL_DELIMITER
Definition: av1.h:31
@ AV1_OBU_TILE_GROUP
Definition: av1.h:33
@ AV1_OBU_FRAME_HEADER
Definition: av1.h:32
@ AV1_OBU_FRAME
Definition: av1.h:35
@ AV1_OBU_SEQUENCE_HEADER
Definition: av1.h:30
#define td
Definition: regdef.h:70
#define FF_ARRAY_ELEMS(a)
CodedBitstreamFragment temporal_unit
CodedBitstreamContext * cbc
AV1RawFrameHeader header
Definition: cbs_av1.h:304
uint8_t obu_type
Definition: cbs_av1.h:31
AV1RawFrameHeader frame_header
Definition: cbs_av1.h:398
AV1RawOBUHeader header
Definition: cbs_av1.h:392
AV1RawTileGroup tile_group
Definition: cbs_av1.h:400
AV1RawFrame frame
Definition: cbs_av1.h:399
union AV1RawOBU::@25 obu
uint16_t tg_end
Definition: cbs_av1.h:298
The bitstream filter state.
Definition: bsf.h:49
const char * name
Definition: bsf.h:99
void * priv_data
Format private data.
Definition: avformat.h:1260
This structure stores compressed data.
Definition: packet.h:346
Context structure for coded bitstream operations.
Definition: cbs.h:170
Coded bitstream fragment structure, combining one or more units.
Definition: cbs.h:118
Coded bitstream unit structure.
Definition: cbs.h:66
void * content
Pointer to the decomposed form of this unit.
Definition: cbs.h:103
CodedBitstreamUnitType type
Codec-specific type of this unit.
Definition: cbs.h:70
size_t data_size
The number of bytes in the bitstream (including any padding bits in the final byte).
Definition: cbs.h:82
#define av_log(a,...)
FILE * out
Definition: movenc.c:54
AVFormatContext * ctx
Definition: movenc.c:48
int size
if(ret< 0)
Definition: vf_mcdeint.c:282