FFmpeg
dirac_parser.c
Go to the documentation of this file.
1 /*
2  * Dirac parser
3  *
4  * Copyright (c) 2007-2008 Marco Gerards <marco@gnu.org>
5  * Copyright (c) 2008 BBC, Anuradha Suraparaju <asuraparaju@gmail.com>
6  *
7  * This file is part of FFmpeg.
8  *
9  * FFmpeg is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * FFmpeg is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with FFmpeg; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
24 /**
25  * @file
26  * Dirac Parser
27  * @author Marco Gerards <marco@gnu.org>
28  */
29 
30 #include <string.h>
31 
32 #include "libavutil/attributes.h"
33 #include "libavutil/intreadwrite.h"
34 #include "libavutil/mem.h"
35 
36 #include "avcodec.h"
37 
38 #define DIRAC_PARSE_INFO_PREFIX 0x42424344
39 
40 /**
41  * Find the end of the current frame in the bitstream.
42  * @return the position of the first byte of the next frame or -1
43  */
44 typedef struct DiracParseContext {
45  int state;
46  int is_synced;
51  int index;
52  uint8_t *buffer;
54  uint8_t *dirac_unit;
56 
58  const uint8_t *buf, int buf_size)
59 {
60  uint32_t state = pc->state;
61  int i = 0;
62 
63  if (!pc->is_synced) {
64  for (i = 0; i < buf_size; i++) {
65  state = (state << 8) | buf[i];
67  state = -1;
68  pc->is_synced = 1;
69  pc->header_bytes_needed = 9;
70  pc->sync_offset = i;
71  break;
72  }
73  }
74  }
75 
76  if (pc->is_synced) {
77  pc->sync_offset = 0;
78  for (; i < buf_size; i++) {
80  if ((buf_size - i) >= pc->header_bytes_needed) {
81  pc->state = -1;
82  return i + pc->header_bytes_needed;
83  } else {
84  pc->header_bytes_needed = 9 - (buf_size - i);
85  break;
86  }
87  } else
88  state = (state << 8) | buf[i];
89  }
90  }
91  pc->state = state;
92  return -1;
93 }
94 
95 typedef struct DiracParseUnit {
98  uint8_t pu_type;
100 
102  int offset)
103 {
104  int i;
105  int8_t *start;
106  static const uint8_t valid_pu_types[] = {
107  0x00, 0x10, 0x20, 0x30, 0x08, 0x48, 0xC8, 0xE8, 0x0A, 0x0C, 0x0D, 0x0E,
108  0x4C, 0x09, 0xCC, 0x88, 0xCB
109  };
110 
111  if (offset < 0 || pc->index - 13 < offset)
112  return 0;
113 
114  start = pc->buffer + offset;
115  pu->pu_type = start[4];
116 
117  pu->next_pu_offset = AV_RB32(start + 5);
118  pu->prev_pu_offset = AV_RB32(start + 9);
119 
120  /* Check for valid parse code */
121  for (i = 0; i < 17; i++)
122  if (valid_pu_types[i] == pu->pu_type)
123  break;
124  if (i == 17)
125  return 0;
126 
127  if (pu->pu_type == 0x10 && pu->next_pu_offset == 0x00)
128  pu->next_pu_offset = 13; /* The length of a parse info header */
129 
130  /* Check if the parse offsets are somewhat sane */
131  if ((pu->next_pu_offset && pu->next_pu_offset < 13) ||
132  (pu->prev_pu_offset && pu->prev_pu_offset < 13))
133  return 0;
134 
135  return 1;
136 }
137 
139  int next, const uint8_t **buf, int *buf_size)
140 {
141  int parse_timing_info = (s->pts == AV_NOPTS_VALUE &&
142  s->dts == AV_NOPTS_VALUE);
143  DiracParseContext *pc = s->priv_data;
144 
145  if (pc->overread_index) {
146  memmove(pc->buffer, pc->buffer + pc->overread_index,
147  pc->index - pc->overread_index);
148  pc->index -= pc->overread_index;
149  pc->overread_index = 0;
150  if (*buf_size == 0 && pc->buffer[4] == 0x10) {
151  *buf = pc->buffer;
152  *buf_size = pc->index;
153  return 0;
154  }
155  }
156 
157  if (next == -1) {
158  /* Found a possible frame start but not a frame end */
159  void *new_buffer =
161  pc->index + (*buf_size - pc->sync_offset));
162  if (!new_buffer)
163  return AVERROR(ENOMEM);
164  pc->buffer = new_buffer;
165  memcpy(pc->buffer + pc->index, (*buf + pc->sync_offset),
166  *buf_size - pc->sync_offset);
167  pc->index += *buf_size - pc->sync_offset;
168  return -1;
169  } else {
170  /* Found a possible frame start and a possible frame end */
171  DiracParseUnit pu1, pu;
172  void *new_buffer = av_fast_realloc(pc->buffer, &pc->buffer_size,
173  pc->index + next);
174  if (!new_buffer)
175  return AVERROR(ENOMEM);
176  pc->buffer = new_buffer;
177  memcpy(pc->buffer + pc->index, *buf, next);
178  pc->index += next;
179 
180  /* Need to check if we have a valid Parse Unit. We can't go by the
181  * sync pattern 'BBCD' alone because arithmetic coding of the residual
182  * and motion data can cause the pattern triggering a false start of
183  * frame. So check if the previous parse offset of the next parse unit
184  * is equal to the next parse offset of the current parse unit then
185  * we can be pretty sure that we have a valid parse unit */
186  if (!unpack_parse_unit(&pu1, pc, pc->index - 13) ||
187  !unpack_parse_unit(&pu, pc, pc->index - 13 - pu1.prev_pu_offset) ||
188  pu.next_pu_offset != pu1.prev_pu_offset ||
189  pc->index < pc->dirac_unit_size + 13LL + pu1.prev_pu_offset
190  ) {
191  pc->index -= 9;
192  *buf_size = next - 9;
193  pc->header_bytes_needed = 9;
194  return -1;
195  }
196 
197  /* All non-frame data must be accompanied by frame data. This is to
198  * ensure that pts is set correctly. So if the current parse unit is
199  * not frame data, wait for frame data to come along */
200 
201  pc->dirac_unit = pc->buffer + pc->index - 13 -
203 
205 
206  if ((pu.pu_type & 0x08) != 0x08) {
207  pc->header_bytes_needed = 9;
208  *buf_size = next;
209  return -1;
210  }
211 
212  /* Get the picture number to set the pts and dts*/
213  if (parse_timing_info && pu1.prev_pu_offset >= 13) {
214  uint8_t *cur_pu = pc->buffer +
215  pc->index - 13 - pu1.prev_pu_offset;
216  int64_t pts = AV_RB32(cur_pu + 13);
217  if (s->last_pts == 0 && s->last_dts == 0)
218  s->dts = pts - 1;
219  else if (s->last_dts != AV_NOPTS_VALUE)
220  s->dts = s->last_dts + 1;
221  s->pts = pts;
222  if (!avctx->has_b_frames && (cur_pu[4] & 0x03))
223  avctx->has_b_frames = 1;
224  }
225  if (avctx->has_b_frames && s->pts == s->dts)
226  s->pict_type = AV_PICTURE_TYPE_B;
227 
228  /* Finally have a complete Dirac data unit */
229  *buf = pc->dirac_unit;
230  *buf_size = pc->dirac_unit_size;
231 
232  pc->dirac_unit_size = 0;
233  pc->overread_index = pc->index - 13;
234  pc->header_bytes_needed = 9;
235  }
236  return next;
237 }
238 
240  const uint8_t **poutbuf, int *poutbuf_size,
241  const uint8_t *buf, int buf_size)
242 {
243  DiracParseContext *pc = s->priv_data;
244  int next;
245 
246  *poutbuf = NULL;
247  *poutbuf_size = 0;
248 
249  if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
250  next = buf_size;
251  *poutbuf = buf;
252  *poutbuf_size = buf_size;
253  /* Assume that data has been packetized into an encapsulation unit. */
254  } else {
255  next = find_frame_end(pc, buf, buf_size);
256  if (!pc->is_synced && next == -1)
257  /* No frame start found yet. So throw away the entire buffer. */
258  return buf_size;
259 
260  if (dirac_combine_frame(s, avctx, next, &buf, &buf_size) < 0)
261  return buf_size;
262  }
263 
264  *poutbuf = buf;
265  *poutbuf_size = buf_size;
266  return next;
267 }
268 
270 {
271  DiracParseContext *pc = s->priv_data;
272 
273  if (pc->buffer_size > 0)
274  av_freep(&pc->buffer);
275 }
276 
279  .priv_data_size = sizeof(DiracParseContext),
280  .parser_parse = dirac_parse,
281  .parser_close = dirac_parse_close,
282 };
DiracParseUnit
Definition: dirac_parser.c:95
DiracParseContext::dirac_unit_size
int dirac_unit_size
Definition: dirac_parser.c:53
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
dirac_combine_frame
static int dirac_combine_frame(AVCodecParserContext *s, AVCodecContext *avctx, int next, const uint8_t **buf, int *buf_size)
Definition: dirac_parser.c:138
dirac_parse_close
static av_cold void dirac_parse_close(AVCodecParserContext *s)
Definition: dirac_parser.c:269
DiracParseContext::buffer
uint8_t * buffer
Definition: dirac_parser.c:52
AV_CODEC_ID_DIRAC
@ AV_CODEC_ID_DIRAC
Definition: codec_id.h:168
int64_t
long long int64_t
Definition: coverity.c:34
DiracParseUnit::next_pu_offset
int next_pu_offset
Definition: dirac_parser.c:96
pts
static int64_t pts
Definition: transcode_aac.c:644
av_cold
#define av_cold
Definition: attributes.h:90
AVCodecContext::has_b_frames
int has_b_frames
Size of the frame reordering buffer in the decoder.
Definition: avcodec.h:697
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:497
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:198
DiracParseContext::state
int state
Definition: dirac_parser.c:45
DiracParseContext::buffer_size
int buffer_size
Definition: dirac_parser.c:50
DiracParseContext::sync_offset
int sync_offset
Definition: dirac_parser.c:47
find_frame_end
static int find_frame_end(DiracParseContext *pc, const uint8_t *buf, int buf_size)
Definition: dirac_parser.c:57
NULL
#define NULL
Definition: coverity.c:32
DiracParseContext::header_bytes_needed
int header_bytes_needed
Definition: dirac_parser.c:48
DiracParseContext::overread_index
int overread_index
Definition: dirac_parser.c:49
index
int index
Definition: gxfenc.c:90
DiracParseContext::index
int index
Definition: dirac_parser.c:51
AVCodecParser::codec_ids
int codec_ids[7]
Definition: avcodec.h:2735
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:247
AV_RB32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
Definition: bytestream.h:96
unpack_parse_unit
static int unpack_parse_unit(DiracParseUnit *pu, DiracParseContext *pc, int offset)
Definition: dirac_parser.c:101
state
static struct @526 state
DiracParseContext
Find the end of the current frame in the bitstream.
Definition: dirac_parser.c:44
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
attributes.h
DiracParseUnit::pu_type
uint8_t pu_type
Definition: dirac_parser.c:98
DiracParseContext::dirac_unit
uint8_t * dirac_unit
Definition: dirac_parser.c:54
dirac_parse
static int dirac_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size)
Definition: dirac_parser.c:239
PARSER_FLAG_COMPLETE_FRAMES
#define PARSER_FLAG_COMPLETE_FRAMES
Definition: avcodec.h:2609
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
avcodec.h
AVCodecParserContext
Definition: avcodec.h:2575
AVCodecContext
main external API structure.
Definition: avcodec.h:431
DiracParseContext::is_synced
int is_synced
Definition: dirac_parser.c:46
ff_dirac_parser
const AVCodecParser ff_dirac_parser
Definition: dirac_parser.c:277
AV_PICTURE_TYPE_B
@ AV_PICTURE_TYPE_B
Bi-dir predicted.
Definition: avutil.h:280
DIRAC_PARSE_INFO_PREFIX
#define DIRAC_PARSE_INFO_PREFIX
Definition: dirac_parser.c:38
mem.h
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
AVCodecParser
Definition: avcodec.h:2734
DiracParseUnit::prev_pu_offset
int prev_pu_offset
Definition: dirac_parser.c:97