FFmpeg
vp9_raw_reorder_bsf.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include "libavutil/avassert.h"
20 #include "libavutil/intmath.h"
21 #include "libavutil/log.h"
22 #include "libavutil/mem.h"
23 #include "libavutil/opt.h"
24 
25 #include "bsf.h"
26 #include "get_bits.h"
27 #include "put_bits.h"
28 
29 #define FRAME_SLOTS 8
30 
31 typedef struct VP9RawReorderFrame {
35 
36  int64_t pts;
37  int64_t sequence;
38  unsigned int slots;
39 
40  unsigned int profile;
41 
42  unsigned int show_existing_frame;
43  unsigned int frame_to_show;
44 
45  unsigned int frame_type;
46  unsigned int show_frame;
47  unsigned int refresh_frame_flags;
49 
50 typedef struct VP9RawReorderContext {
51  int64_t sequence;
55 
57 {
58  if (*frame)
59  av_packet_free(&(*frame)->packet);
60  av_freep(frame);
61 }
62 
64 {
65  if (ctx->slot[s]) {
66  ctx->slot[s]->slots &= ~(1 << s);
67  if (ctx->slot[s]->slots == 0)
69  else
70  ctx->slot[s] = NULL;
71  }
72 }
73 
75 {
76  GetBitContext bc;
77  int err;
78 
79  unsigned int frame_marker;
80  unsigned int profile_low_bit, profile_high_bit, reserved_zero;
81  unsigned int error_resilient_mode;
82  unsigned int frame_sync_code;
83 
84  err = init_get_bits(&bc, frame->packet->data, 8 * frame->packet->size);
85  if (err)
86  return err;
87 
88  frame_marker = get_bits(&bc, 2);
89  if (frame_marker != 2) {
90  av_log(bsf, AV_LOG_ERROR, "Invalid frame marker: %u.\n",
91  frame_marker);
92  return AVERROR_INVALIDDATA;
93  }
94 
95  profile_low_bit = get_bits1(&bc);
96  profile_high_bit = get_bits1(&bc);
97  frame->profile = (profile_high_bit << 1) | profile_low_bit;
98  if (frame->profile == 3) {
99  reserved_zero = get_bits1(&bc);
100  if (reserved_zero != 0) {
101  av_log(bsf, AV_LOG_ERROR, "Profile reserved_zero bit set: "
102  "unsupported profile or invalid bitstream.\n");
103  return AVERROR_INVALIDDATA;
104  }
105  }
106 
107  frame->show_existing_frame = get_bits1(&bc);
108  if (frame->show_existing_frame) {
109  frame->frame_to_show = get_bits(&bc, 3);
110  return 0;
111  }
112 
113  frame->frame_type = get_bits1(&bc);
114  frame->show_frame = get_bits1(&bc);
115  error_resilient_mode = get_bits1(&bc);
116 
117  if (frame->frame_type == 0) {
118  frame_sync_code = get_bits(&bc, 24);
119  if (frame_sync_code != 0x498342) {
120  av_log(bsf, AV_LOG_ERROR, "Invalid frame sync code: %06x.\n",
121  frame_sync_code);
122  return AVERROR_INVALIDDATA;
123  }
124  frame->refresh_frame_flags = 0xff;
125  } else {
126  unsigned int intra_only;
127 
128  if (frame->show_frame == 0)
129  intra_only = get_bits1(&bc);
130  else
131  intra_only = 0;
132  if (error_resilient_mode == 0) {
133  // reset_frame_context
134  skip_bits(&bc, 2);
135  }
136  if (intra_only) {
137  frame_sync_code = get_bits(&bc, 24);
138  if (frame_sync_code != 0x498342) {
139  av_log(bsf, AV_LOG_ERROR, "Invalid frame sync code: "
140  "%06x.\n", frame_sync_code);
141  return AVERROR_INVALIDDATA;
142  }
143  if (frame->profile > 0) {
144  unsigned int color_space;
145  if (frame->profile >= 2) {
146  // ten_or_twelve_bit
147  skip_bits(&bc, 1);
148  }
149  color_space = get_bits(&bc, 3);
150  if (color_space != 7 /* CS_RGB */) {
151  // color_range
152  skip_bits(&bc, 1);
153  if (frame->profile == 1 || frame->profile == 3) {
154  // subsampling
155  skip_bits(&bc, 3);
156  }
157  } else {
158  if (frame->profile == 1 || frame->profile == 3)
159  skip_bits(&bc, 1);
160  }
161  }
162  frame->refresh_frame_flags = get_bits(&bc, 8);
163  } else {
164  frame->refresh_frame_flags = get_bits(&bc, 8);
165  }
166  }
167 
168  return 0;
169 }
170 
172  AVPacket *out,
173  VP9RawReorderFrame *last_frame)
174 {
176  VP9RawReorderFrame *next_output = last_frame,
177  *next_display = last_frame, *frame;
178  int s, err;
179 
180  for (s = 0; s < FRAME_SLOTS; s++) {
181  frame = ctx->slot[s];
182  if (!frame)
183  continue;
184  if (frame->needs_output && (!next_output ||
185  frame->sequence < next_output->sequence))
186  next_output = frame;
187  if (frame->needs_display && (!next_display ||
188  frame->pts < next_display->pts))
189  next_display = frame;
190  }
191 
192  if (!next_output && !next_display)
193  return AVERROR_EOF;
194 
195  if (!next_display || (next_output &&
196  next_output->sequence < next_display->sequence))
197  frame = next_output;
198  else
199  frame = next_display;
200 
201  if (frame->needs_output && frame->needs_display &&
202  next_output == next_display) {
203  av_log(bsf, AV_LOG_DEBUG, "Output and display frame "
204  "%"PRId64" (%"PRId64") in order.\n",
205  frame->sequence, frame->pts);
206 
207  av_packet_move_ref(out, frame->packet);
208 
209  frame->needs_output = frame->needs_display = 0;
210  } else if (frame->needs_output) {
211  if (frame->needs_display) {
212  av_log(bsf, AV_LOG_DEBUG, "Output frame %"PRId64" "
213  "(%"PRId64") for later display.\n",
214  frame->sequence, frame->pts);
215  } else {
216  av_log(bsf, AV_LOG_DEBUG, "Output unshown frame "
217  "%"PRId64" (%"PRId64") to keep order.\n",
218  frame->sequence, frame->pts);
219  }
220 
221  av_packet_move_ref(out, frame->packet);
222  out->pts = out->dts;
223 
224  frame->needs_output = 0;
225  } else {
226  PutBitContext pb;
227 
228  av_assert0(!frame->needs_output && frame->needs_display);
229 
230  if (frame->slots == 0) {
231  av_log(bsf, AV_LOG_ERROR, "Attempting to display frame "
232  "which is no longer available?\n");
233  frame->needs_display = 0;
234  return AVERROR_INVALIDDATA;
235  }
236 
237  s = ff_ctz(frame->slots);
238  av_assert0(s < FRAME_SLOTS);
239 
240  av_log(bsf, AV_LOG_DEBUG, "Display frame %"PRId64" "
241  "(%"PRId64") from slot %d.\n",
242  frame->sequence, frame->pts, s);
243 
244  err = av_new_packet(out, 2);
245  if (err < 0)
246  return err;
247 
248  init_put_bits(&pb, out->data, 2);
249 
250  // frame_marker
251  put_bits(&pb, 2, 2);
252  // profile_low_bit
253  put_bits(&pb, 1, frame->profile & 1);
254  // profile_high_bit
255  put_bits(&pb, 1, (frame->profile >> 1) & 1);
256  if (frame->profile == 3) {
257  // reserved_zero
258  put_bits(&pb, 1, 0);
259  }
260  // show_existing_frame
261  put_bits(&pb, 1, 1);
262  // frame_to_show_map_idx
263  put_bits(&pb, 3, s);
264 
265  while (put_bits_count(&pb) < 16)
266  put_bits(&pb, 1, 0);
267 
268  flush_put_bits(&pb);
269  out->pts = out->dts = frame->pts;
270 
271  frame->needs_display = 0;
272  }
273 
274  return 0;
275 }
276 
278 {
281  AVPacket *in;
282  int err, s;
283 
284  if (ctx->next_frame) {
285  frame = ctx->next_frame;
286 
287  } else {
288  err = ff_bsf_get_packet(bsf, &in);
289  if (err < 0) {
290  if (err == AVERROR_EOF)
291  return vp9_raw_reorder_make_output(bsf, out, NULL);
292  return err;
293  }
294 
295  if (in->data[in->size - 1] & 0xe0 == 0xc0) {
296  av_log(bsf, AV_LOG_ERROR, "Input in superframes is not "
297  "supported.\n");
298  av_packet_free(&in);
299  return AVERROR(ENOSYS);
300  }
301 
302  frame = av_mallocz(sizeof(*frame));
303  if (!frame) {
304  av_packet_free(&in);
305  return AVERROR(ENOMEM);
306  }
307 
308  frame->packet = in;
309  frame->pts = in->pts;
310  frame->sequence = ++ctx->sequence;
311  err = vp9_raw_reorder_frame_parse(bsf, frame);
312  if (err) {
313  av_log(bsf, AV_LOG_ERROR, "Failed to parse input "
314  "frame: %d.\n", err);
315  goto fail;
316  }
317 
318  frame->needs_output = 1;
319  frame->needs_display = frame->pts != AV_NOPTS_VALUE;
320 
321  if (frame->show_existing_frame)
322  av_log(bsf, AV_LOG_DEBUG, "Show frame %"PRId64" "
323  "(%"PRId64"): show %u.\n", frame->sequence,
324  frame->pts, frame->frame_to_show);
325  else
326  av_log(bsf, AV_LOG_DEBUG, "New frame %"PRId64" "
327  "(%"PRId64"): type %u show %u refresh %02x.\n",
328  frame->sequence, frame->pts, frame->frame_type,
329  frame->show_frame, frame->refresh_frame_flags);
330 
331  ctx->next_frame = frame;
332  }
333 
334  for (s = 0; s < FRAME_SLOTS; s++) {
335  if (!(frame->refresh_frame_flags & (1 << s)))
336  continue;
337  if (ctx->slot[s] && ctx->slot[s]->needs_display &&
338  ctx->slot[s]->slots == (1 << s)) {
339  // We are overwriting this slot, which is last reference
340  // to the frame previously present in it. In order to be
341  // a valid stream, that frame must already have been
342  // displayed before the pts of the current frame.
343  err = vp9_raw_reorder_make_output(bsf, out, ctx->slot[s]);
344  if (err < 0) {
345  av_log(bsf, AV_LOG_ERROR, "Failed to create "
346  "output overwriting slot %d: %d.\n",
347  s, err);
348  // Clear the slot anyway, so we don't end up
349  // in an infinite loop.
351  return AVERROR_INVALIDDATA;
352  }
353  return 0;
354  }
356  }
357 
358  for (s = 0; s < FRAME_SLOTS; s++) {
359  if (!(frame->refresh_frame_flags & (1 << s)))
360  continue;
361  ctx->slot[s] = frame;
362  }
363  frame->slots = frame->refresh_frame_flags;
364 
365  if (!frame->refresh_frame_flags) {
366  err = vp9_raw_reorder_make_output(bsf, out, frame);
367  if (err < 0) {
368  av_log(bsf, AV_LOG_ERROR, "Failed to create output "
369  "for transient frame.\n");
370  ctx->next_frame = NULL;
371  return AVERROR_INVALIDDATA;
372  }
373  if (!frame->needs_display) {
375  ctx->next_frame = NULL;
376  }
377  return 0;
378  }
379 
380  ctx->next_frame = NULL;
381  return AVERROR(EAGAIN);
382 
383 fail:
385  return err;
386 }
387 
389 {
391 
392  for (int s = 0; s < FRAME_SLOTS; s++)
394  ctx->next_frame = NULL;
395  ctx->sequence = 0;
396 }
397 
399 {
401  int s;
402 
403  for (s = 0; s < FRAME_SLOTS; s++)
405 }
406 
407 static const enum AVCodecID vp9_raw_reorder_codec_ids[] = {
409 };
410 
412  .name = "vp9_raw_reorder",
413  .priv_data_size = sizeof(VP9RawReorderContext),
414  .close = &vp9_raw_reorder_close,
418 };
#define NULL
Definition: coverity.c:32
#define ff_ctz
Definition: intmath.h:106
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static void flush(AVCodecContext *avctx)
static void put_bits(Jpeg2000EncoderContext *s, int val, int n)
put n times val bit
Definition: j2kenc.c:208
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:379
Memory handling functions.
The bitstream filter state.
Definition: avcodec.h:5759
int size
Definition: avcodec.h:1478
unsigned int frame_to_show
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:236
void * priv_data
Opaque filter-specific private data.
Definition: avcodec.h:5780
static int vp9_raw_reorder_filter(AVBSFContext *bsf, AVPacket *out)
static void vp9_raw_reorder_close(AVBSFContext *bsf)
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
static int vp9_raw_reorder_frame_parse(AVBSFContext *bsf, VP9RawReorderFrame *frame)
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: avpacket.c:62
const AVBitStreamFilter ff_vp9_raw_reorder_bsf
AVOptions.
static void vp9_raw_reorder_flush(AVBSFContext *bsf)
const char * name
Definition: avcodec.h:5809
uint8_t * data
Definition: avcodec.h:1477
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition: avpacket.c:655
static int FUNC() frame_sync_code(CodedBitstreamContext *ctx, RWContext *rw, VP9RawFrameHeader *current)
#define AVERROR_EOF
End of file.
Definition: error.h:55
bitstream reader API header.
#define av_log(a,...)
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:86
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: avcodec.h:215
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
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
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
simple assert() macros that are a bit more flexible than ISO C assert().
VP9RawReorderFrame * next_frame
#define fail()
Definition: checkasm.h:120
static int put_bits_count(PutBitContext *s)
Definition: put_bits.h:85
int intra_only
Definition: mxfenc.c:2219
AVFormatContext * ctx
Definition: movenc.c:48
#define FRAME_SLOTS
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
#define s(width, name)
Definition: cbs_vp9.c:257
unsigned int refresh_frame_flags
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:498
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);return NULL;}return ac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
static void vp9_raw_reorder_clear_slot(VP9RawReorderContext *ctx, int s)
static void skip_bits(GetBitContext *s, int n)
Definition: get_bits.h:467
VP9RawReorderFrame * slot[FRAME_SLOTS]
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition: get_bits.h:659
static void flush_put_bits(PutBitContext *s)
Pad the end of the output stream with zeros.
Definition: put_bits.h:101
static enum AVCodecID codec_ids[]
int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt)
Called by the bitstream filters to get the next packet for filtering.
Definition: bsf.c:216
static void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
Initialize the PutBitContext s.
Definition: put_bits.h:48
static enum AVCodecID vp9_raw_reorder_codec_ids[]
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
Definition: avcodec.h:1476
static void vp9_raw_reorder_frame_free(VP9RawReorderFrame **frame)
FILE * out
Definition: movenc.c:54
#define av_freep(p)
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
static int vp9_raw_reorder_make_output(AVBSFContext *bsf, AVPacket *out, VP9RawReorderFrame *last_frame)
This structure stores compressed data.
Definition: avcodec.h:1454
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1470
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
unsigned int show_existing_frame
bitstream writer API