libschroedingerdec.c
Go to the documentation of this file.
1 /*
2  * Dirac decoder support via Schroedinger libraries
3  * Copyright (c) 2008 BBC, Anuradha Suraparaju <asuraparaju at gmail dot com >
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23 * @file
24 * Dirac decoder support via libschroedinger-1.0 libraries. More details about
25 * the Schroedinger project can be found at http://www.diracvideo.org/.
26 * The library implements Dirac Specification Version 2.2.
27 * (http://dirac.sourceforge.net/specification.html).
28 */
29 
30 #include <string.h>
31 
32 #include "libavutil/imgutils.h"
33 #include "libavutil/internal.h"
34 #include "libavutil/intreadwrite.h"
35 #include "libavutil/mem.h"
36 #include "avcodec.h"
37 #include "internal.h"
38 #include "libschroedinger.h"
39 
40 #include <schroedinger/schro.h>
41 #include <schroedinger/schrodebug.h>
42 #include <schroedinger/schrovideoformat.h>
43 
44 /** SchroFrame and Pts relation */
45 typedef struct LibSchroFrameContext {
46  SchroFrame *frame;
47  int64_t pts;
49 
50 /** libschroedinger decoder private data */
51 typedef struct SchroDecoderParams {
52  /** Schroedinger video format */
53  SchroVideoFormat *format;
54 
55  /** Schroedinger frame format */
56  SchroFrameFormat frame_format;
57 
58  /** decoder handle */
59  SchroDecoder* decoder;
60 
61  /** queue storing decoded frames */
63 
64  /** end of sequence signalled */
66 
67  /** end of sequence pulled */
70 
71 typedef struct SchroParseUnitContext {
72  const uint8_t *buf;
73  int buf_size;
75 
76 
77 static void libschroedinger_decode_buffer_free(SchroBuffer *schro_buf,
78  void *priv)
79 {
80  av_freep(&priv);
81 }
82 
84  const uint8_t *buf, int buf_size)
85 {
86  parse_ctx->buf = buf;
87  parse_ctx->buf_size = buf_size;
88 }
89 
90 static SchroBuffer *find_next_parse_unit(SchroParseUnitContext *parse_ctx)
91 {
92  SchroBuffer *enc_buf = NULL;
93  int next_pu_offset = 0;
94  unsigned char *in_buf;
95 
96  if (parse_ctx->buf_size < 13 ||
97  parse_ctx->buf[0] != 'B' ||
98  parse_ctx->buf[1] != 'B' ||
99  parse_ctx->buf[2] != 'C' ||
100  parse_ctx->buf[3] != 'D')
101  return NULL;
102 
103  next_pu_offset = (parse_ctx->buf[5] << 24) +
104  (parse_ctx->buf[6] << 16) +
105  (parse_ctx->buf[7] << 8) +
106  parse_ctx->buf[8];
107 
108  if (next_pu_offset == 0 &&
109  SCHRO_PARSE_CODE_IS_END_OF_SEQUENCE(parse_ctx->buf[4]))
110  next_pu_offset = 13;
111 
112  if (next_pu_offset <= 0 || parse_ctx->buf_size < next_pu_offset)
113  return NULL;
114 
115  in_buf = av_malloc(next_pu_offset);
116  if (!in_buf) {
117  av_log(parse_ctx, AV_LOG_ERROR, "Unable to allocate input buffer\n");
118  return NULL;
119  }
120 
121  memcpy(in_buf, parse_ctx->buf, next_pu_offset);
122  enc_buf = schro_buffer_new_with_data(in_buf, next_pu_offset);
123  enc_buf->free = libschroedinger_decode_buffer_free;
124  enc_buf->priv = in_buf;
125 
126  parse_ctx->buf += next_pu_offset;
127  parse_ctx->buf_size -= next_pu_offset;
128 
129  return enc_buf;
130 }
131 
132 /**
133 * Returns FFmpeg chroma format.
134 */
135 static enum AVPixelFormat get_chroma_format(SchroChromaFormat schro_pix_fmt)
136 {
137  int num_formats = sizeof(schro_pixel_format_map) /
138  sizeof(schro_pixel_format_map[0]);
139  int idx;
140 
141  for (idx = 0; idx < num_formats; ++idx)
142  if (schro_pixel_format_map[idx].schro_pix_fmt == schro_pix_fmt)
143  return schro_pixel_format_map[idx].ff_pix_fmt;
144  return AV_PIX_FMT_NONE;
145 }
146 
148 {
149 
150  SchroDecoderParams *p_schro_params = avctx->priv_data;
151  /* First of all, initialize our supporting libraries. */
152  schro_init();
153 
154  schro_debug_set_level(avctx->debug);
155  p_schro_params->decoder = schro_decoder_new();
156  schro_decoder_set_skip_ratio(p_schro_params->decoder, 1);
157 
158  if (!p_schro_params->decoder)
159  return -1;
160 
161  /* Initialize the decoded frame queue. */
162  ff_schro_queue_init(&p_schro_params->dec_frame_queue);
163  return 0;
164 }
165 
167 {
168  schro_frame_unref(frame);
169 }
170 
172 {
173  SchroDecoderParams *p_schro_params = avctx->priv_data;
174  SchroDecoder *decoder = p_schro_params->decoder;
175 
176  p_schro_params->format = schro_decoder_get_video_format(decoder);
177 
178  /* Tell FFmpeg about sequence details. */
179  if (av_image_check_size(p_schro_params->format->width,
180  p_schro_params->format->height, 0, avctx) < 0) {
181  av_log(avctx, AV_LOG_ERROR, "invalid dimensions (%dx%d)\n",
182  p_schro_params->format->width, p_schro_params->format->height);
183  avctx->height = avctx->width = 0;
184  return;
185  }
186  avctx->height = p_schro_params->format->height;
187  avctx->width = p_schro_params->format->width;
188  avctx->pix_fmt = get_chroma_format(p_schro_params->format->chroma_format);
189 
190  if (ff_get_schro_frame_format(p_schro_params->format->chroma_format,
191  &p_schro_params->frame_format) == -1) {
192  av_log(avctx, AV_LOG_ERROR,
193  "This codec currently only supports planar YUV 4:2:0, 4:2:2 "
194  "and 4:4:4 formats.\n");
195  return;
196  }
197 
198  avctx->time_base.den = p_schro_params->format->frame_rate_numerator;
199  avctx->time_base.num = p_schro_params->format->frame_rate_denominator;
200 }
201 
203  void *data, int *got_frame,
204  AVPacket *avpkt)
205 {
206  const uint8_t *buf = avpkt->data;
207  int buf_size = avpkt->size;
208  int64_t pts = avpkt->pts;
209  SchroTag *tag;
210 
211  SchroDecoderParams *p_schro_params = avctx->priv_data;
212  SchroDecoder *decoder = p_schro_params->decoder;
213  SchroBuffer *enc_buf;
214  SchroFrame* frame;
215  AVFrame *avframe = data;
216  int state;
217  int go = 1;
218  int outer = 1;
219  SchroParseUnitContext parse_ctx;
220  LibSchroFrameContext *framewithpts = NULL;
221 
222  *got_frame = 0;
223 
224  parse_context_init(&parse_ctx, buf, buf_size);
225  if (!buf_size) {
226  if (!p_schro_params->eos_signalled) {
227  state = schro_decoder_push_end_of_stream(decoder);
228  p_schro_params->eos_signalled = 1;
229  }
230  }
231 
232  /* Loop through all the individual parse units in the input buffer */
233  do {
234  if ((enc_buf = find_next_parse_unit(&parse_ctx))) {
235  /* Set Schrotag with the pts to be recovered after decoding*/
236  enc_buf->tag = schro_tag_new(av_malloc(sizeof(int64_t)), av_free);
237  if (!enc_buf->tag->value) {
238  av_log(avctx, AV_LOG_ERROR, "Unable to allocate SchroTag\n");
239  return AVERROR(ENOMEM);
240  }
241  AV_WN(64, enc_buf->tag->value, pts);
242  /* Push buffer into decoder. */
243  if (SCHRO_PARSE_CODE_IS_PICTURE(enc_buf->data[4]) &&
244  SCHRO_PARSE_CODE_NUM_REFS(enc_buf->data[4]) > 0)
245  avctx->has_b_frames = 1;
246  state = schro_decoder_push(decoder, enc_buf);
247  if (state == SCHRO_DECODER_FIRST_ACCESS_UNIT)
249  go = 1;
250  } else
251  outer = 0;
252 
253  while (go) {
254  /* Parse data and process result. */
255  state = schro_decoder_wait(decoder);
256  switch (state) {
257  case SCHRO_DECODER_FIRST_ACCESS_UNIT:
259  break;
260 
261  case SCHRO_DECODER_NEED_BITS:
262  /* Need more input data - stop iterating over what we have. */
263  go = 0;
264  break;
265 
266  case SCHRO_DECODER_NEED_FRAME:
267  /* Decoder needs a frame - create one and push it in. */
268  frame = ff_create_schro_frame(avctx,
269  p_schro_params->frame_format);
270  schro_decoder_add_output_picture(decoder, frame);
271  break;
272 
273  case SCHRO_DECODER_OK:
274  /* Pull a frame out of the decoder. */
275  tag = schro_decoder_get_picture_tag(decoder);
276  frame = schro_decoder_pull(decoder);
277 
278  if (frame) {
279  /* Add relation between schroframe and pts. */
280  framewithpts = av_malloc(sizeof(LibSchroFrameContext));
281  if (!framewithpts) {
282  av_log(avctx, AV_LOG_ERROR, "Unable to allocate FrameWithPts\n");
283  return AVERROR(ENOMEM);
284  }
285  framewithpts->frame = frame;
286  framewithpts->pts = AV_RN64(tag->value);
287  ff_schro_queue_push_back(&p_schro_params->dec_frame_queue,
288  framewithpts);
289  }
290  break;
291  case SCHRO_DECODER_EOS:
292  go = 0;
293  p_schro_params->eos_pulled = 1;
294  schro_decoder_reset(decoder);
295  outer = 0;
296  break;
297 
298  case SCHRO_DECODER_ERROR:
299  return -1;
300  break;
301  }
302  }
303  } while (outer);
304 
305  /* Grab next frame to be returned from the top of the queue. */
306  framewithpts = ff_schro_queue_pop(&p_schro_params->dec_frame_queue);
307 
308  if (framewithpts && framewithpts->frame) {
309  int ret;
310 
311  if ((ret = ff_get_buffer(avctx, avframe, 0)) < 0)
312  return ret;
313 
314  memcpy(avframe->data[0],
315  framewithpts->frame->components[0].data,
316  framewithpts->frame->components[0].length);
317 
318  memcpy(avframe->data[1],
319  framewithpts->frame->components[1].data,
320  framewithpts->frame->components[1].length);
321 
322  memcpy(avframe->data[2],
323  framewithpts->frame->components[2].data,
324  framewithpts->frame->components[2].length);
325 
326  /* Fill frame with current buffer data from Schroedinger. */
327  avframe->pkt_pts = framewithpts->pts;
328  avframe->linesize[0] = framewithpts->frame->components[0].stride;
329  avframe->linesize[1] = framewithpts->frame->components[1].stride;
330  avframe->linesize[2] = framewithpts->frame->components[2].stride;
331 
332  *got_frame = 1;
333 
334  /* Now free the frame resources. */
336  av_free(framewithpts);
337  } else {
338  data = NULL;
339  *got_frame = 0;
340  }
341  return buf_size;
342 }
343 
344 
346 {
347  SchroDecoderParams *p_schro_params = avctx->priv_data;
348  /* Free the decoder. */
349  schro_decoder_free(p_schro_params->decoder);
350  av_freep(&p_schro_params->format);
351 
352  /* Free data in the output frame queue. */
353  ff_schro_queue_free(&p_schro_params->dec_frame_queue,
355 
356  return 0;
357 }
358 
360 {
361  /* Got a seek request. Free the decoded frames queue and then reset
362  * the decoder */
363  SchroDecoderParams *p_schro_params = avctx->priv_data;
364 
365  /* Free data in the output frame queue. */
366  ff_schro_queue_free(&p_schro_params->dec_frame_queue,
368 
369  ff_schro_queue_init(&p_schro_params->dec_frame_queue);
370  schro_decoder_reset(p_schro_params->decoder);
371  p_schro_params->eos_pulled = 0;
372  p_schro_params->eos_signalled = 0;
373 }
374 
376  .name = "libschroedinger",
377  .type = AVMEDIA_TYPE_VIDEO,
378  .id = AV_CODEC_ID_DIRAC,
379  .priv_data_size = sizeof(SchroDecoderParams),
383  .capabilities = CODEC_CAP_DELAY,
385  .long_name = NULL_IF_CONFIG_SMALL("libschroedinger Dirac 2.2"),
386 };
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
struct LibSchroFrameContext LibSchroFrameContext
SchroFrame and Pts relation.
misc image utilities
SchroChromaFormat schro_pix_fmt
memory handling functions
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
SchroFrame * ff_create_schro_frame(AVCodecContext *avctx, SchroFrameFormat schro_frame_fmt)
Create a Schro frame based on the dimensions and frame format passed.
SchroVideoFormat * format
Schroedinger video format.
int num
numerator
Definition: rational.h:44
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
static av_cold int libschroedinger_decode_init(AVCodecContext *avctx)
static SchroBuffer * find_next_parse_unit(SchroParseUnitContext *parse_ctx)
static enum AVPixelFormat get_chroma_format(SchroChromaFormat schro_pix_fmt)
Returns FFmpeg chroma format.
data structures common to libschroedinger decoder and encoder
static void libschroedinger_decode_buffer_free(SchroBuffer *schro_buf, void *priv)
SchroFrameFormat frame_format
Schroedinger frame format.
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
initialize output if(nPeaks >3)%at least 3 peaks in spectrum for trying to find f0 nf0peaks
uint8_t
#define av_cold
Definition: attributes.h:78
#define AV_WN(s, p, v)
Definition: intreadwrite.h:346
SchroDecoder * decoder
decoder handle
uint8_t * data
uint32_t tag
Definition: movenc.c:894
struct SchroDecoderParams SchroDecoderParams
libschroedinger decoder private data
int has_b_frames
Size of the frame reordering buffer in the decoder.
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
#define CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
void * ff_schro_queue_pop(FFSchroQueue *queue)
Return the first element in the queue.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Spectrum Plot time data
void ff_schro_queue_init(FFSchroQueue *queue)
Initialise the queue.
AVCodec ff_libschroedinger_decoder
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
const char * name
Name of the codec implementation.
external API header
static av_cold int libschroedinger_decode_close(AVCodecContext *avctx)
static void libschroedinger_flush(AVCodecContext *avctx)
int ff_get_schro_frame_format(SchroChromaFormat schro_pix_fmt, SchroFrameFormat *schro_frame_fmt)
Sets the Schroedinger frame format corresponding to the Schro chroma format passed.
common internal API header
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition: imgutils.c:231
int ff_schro_queue_push_back(FFSchroQueue *queue, void *p_data)
Add an element to the end of the queue.
void ff_schro_queue_free(FFSchroQueue *queue, void(*free_func)(void *))
Free the queue resources.
A simple queue implementation used in libschroedinger.
ret
Definition: avfilter.c:821
static const chunk_decoder decoder[8]
int width
picture width / height.
libschroedinger decoder private data
static void flush(AVCodecContext *avctx)
SchroFrame and Pts relation.
static const struct @67 schro_pixel_format_map[]
NULL
Definition: eval.c:55
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:101
main external API structure.
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:375
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void * buf
Definition: avisynth_c.h:594
static int libschroedinger_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
int eos_signalled
end of sequence signalled
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer 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.Buffer references ownership and permissions
FFSchroQueue dec_frame_queue
queue storing decoded frames
int64_t pkt_pts
PTS copied from the AVPacket that was decoded to produce this frame.
Definition: frame.h:164
static uint32_t state
Definition: trasher.c:27
int eos_pulled
end of sequence pulled
static void parse_context_init(SchroParseUnitContext *parse_ctx, const uint8_t *buf, int buf_size)
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
common internal api header.
int den
denominator
Definition: rational.h:45
#define AV_RN64(p)
Definition: intreadwrite.h:360
struct SchroParseUnitContext SchroParseUnitContext
static int decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: crystalhd.c:868
static void libschroedinger_decode_frame_free(void *frame)
static void libschroedinger_handle_first_access_unit(AVCodecContext *avctx)
AVPixelFormat
Pixel format.
Definition: pixfmt.h:66
This structure stores compressed data.
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...