FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
oggparsedaala.c
Go to the documentation of this file.
1 /*
2  * Ogg Daala parser
3  * Copyright (C) 2015 Rostislav Pehlivanov <atomnuker gmail com>
4  * Copyright (C) 2015 Vittorio Giovara <vittorio.giovara gmail com>
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include <stdlib.h>
24 #include "libavcodec/bytestream.h"
25 #include "avformat.h"
26 #include "internal.h"
27 #include "oggdec.h"
28 
31  int depth;
32  int planes;
33  int xdec[4];
34  int ydec[4];
35 };
36 
37 /* Currently supported formats only */
38 static const struct DaalaPixFmtMap list_fmts[] = {
39  { AV_PIX_FMT_YUV420P, 8, 3, {0, 1, 1, 0}, {0, 1, 1, 0} },
40  { AV_PIX_FMT_YUV444P, 8, 3, {0, 0, 0, 0}, {0, 0, 0, 0} }
41 };
42 
43 typedef struct DaalaInfoHeader {
44  int init_d;
45  int fpr;
46  int gpshift;
47  int gpmask;
55 
56 static inline int daala_match_pix_fmt(struct DaalaPixFmtMap *fmt)
57 {
58  int i, j;
59  for (i = 0; i < FF_ARRAY_ELEMS(list_fmts); i++) {
60  int match = 0;
61  if (fmt->depth != list_fmts[i].depth)
62  continue;
63  if (fmt->planes != list_fmts[i].planes)
64  continue;
65  for (j = 0; j < fmt->planes; j++) {
66  if (fmt->xdec[j] != list_fmts[i].xdec[j])
67  continue;
68  if (fmt->ydec[j] != list_fmts[i].ydec[j])
69  continue;
70  match++;
71  }
72  if (match == fmt->planes)
73  return list_fmts[i].ffmpeg_fmt;
74  }
75  return -1;
76 }
77 
78 static int daala_header(AVFormatContext *s, int idx)
79 {
80  int i, err;
81  uint8_t *cdp;
82  GetByteContext gb;
83  AVRational timebase;
84  struct ogg *ogg = s->priv_data;
85  struct ogg_stream *os = ogg->streams + idx;
86  AVStream *st = s->streams[idx];
87  int cds = st->codecpar->extradata_size + os->psize + 2;
88  DaalaInfoHeader *hdr = os->private;
89 
90  if (!(os->buf[os->pstart] & 0x80))
91  return 0;
92 
93  if (!hdr) {
94  hdr = av_mallocz(sizeof(*hdr));
95  if (!hdr)
96  return AVERROR(ENOMEM);
97  os->private = hdr;
98  }
99 
100  switch (os->buf[os->pstart]) {
101  case 0x80:
102  bytestream2_init(&gb, os->buf + os->pstart, os->psize);
104 
105  hdr->version_maj = bytestream2_get_byte(&gb);
106  hdr->version_min = bytestream2_get_byte(&gb);
107  hdr->version_sub = bytestream2_get_byte(&gb);
108 
109  st->codecpar->width = bytestream2_get_ne32(&gb);
111 
114 
115  timebase.num = bytestream2_get_ne32(&gb);
116  timebase.den = bytestream2_get_ne32(&gb);
117  if (timebase.num < 0 && timebase.den < 0) {
118  av_log(s, AV_LOG_WARNING, "Invalid timebase, assuming 30 FPS\n");
119  timebase.num = 1;
120  timebase.den = 30;
121  }
122  avpriv_set_pts_info(st, 64, timebase.den, timebase.num);
123 
125  hdr->gpshift = bytestream2_get_byte(&gb);
126  if (hdr->gpshift >= 32) {
127  av_log(s, AV_LOG_ERROR, "Too large gpshift %d (>= 32).\n",
128  hdr->gpshift);
129  return AVERROR_INVALIDDATA;
130  }
131  hdr->gpmask = (1U << hdr->gpshift) - 1;
132 
133  hdr->format.depth = 8 + 2*(bytestream2_get_byte(&gb)-1);
134 
135  hdr->fpr = bytestream2_get_byte(&gb);
136 
137  hdr->format.planes = bytestream2_get_byte(&gb);
138  if (hdr->format.planes > 4) {
139  av_log(s, AV_LOG_ERROR,
140  "Invalid number of planes %d in daala pixel format map.\n",
141  hdr->format.planes);
142  return AVERROR_INVALIDDATA;
143  }
144  for (i = 0; i < hdr->format.planes; i++) {
145  hdr->format.xdec[i] = bytestream2_get_byte(&gb);
146  hdr->format.ydec[i] = bytestream2_get_byte(&gb);
147  }
148 
149  if ((st->codecpar->format = daala_match_pix_fmt(&hdr->format)) < 0)
150  av_log(s, AV_LOG_ERROR, "Unsupported pixel format - %i %i\n",
151  hdr->format.depth, hdr->format.planes);
152 
156 
157  hdr->init_d = 1;
158  break;
159  case 0x81:
160  if (!hdr->init_d)
161  return AVERROR_INVALIDDATA;
163  os->buf + os->pstart + ff_daala_codec.magicsize,
165  break;
166  case 0x82:
167  if (!hdr->init_d)
168  return AVERROR_INVALIDDATA;
169  break;
170  default:
171  av_log(s, AV_LOG_ERROR, "Unknown header type %X\n", os->buf[os->pstart]);
172  return AVERROR_INVALIDDATA;
173  break;
174  }
175 
176  if ((err = av_reallocp(&st->codecpar->extradata,
177  cds + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
178  st->codecpar->extradata_size = 0;
179  return err;
180  }
181 
182  memset(st->codecpar->extradata + cds, 0, AV_INPUT_BUFFER_PADDING_SIZE);
183  cdp = st->codecpar->extradata + st->codecpar->extradata_size;
184  *cdp++ = os->psize >> 8;
185  *cdp++ = os->psize & 0xff;
186  memcpy(cdp, os->buf + os->pstart, os->psize);
187  st->codecpar->extradata_size = cds;
188 
189  return 1;
190 }
191 
192 static uint64_t daala_gptopts(AVFormatContext *ctx, int idx, uint64_t gp,
193  int64_t *dts)
194 {
195  uint64_t iframe, pframe;
196  struct ogg *ogg = ctx->priv_data;
197  struct ogg_stream *os = ogg->streams + idx;
198  DaalaInfoHeader *hdr = os->private;
199 
200  if (!hdr)
201  return AV_NOPTS_VALUE;
202 
203  iframe = gp >> hdr->gpshift;
204  pframe = gp & hdr->gpmask;
205 
206  if (!pframe)
207  os->pflags |= AV_PKT_FLAG_KEY;
208 
209  if (dts)
210  *dts = iframe + pframe;
211 
212  return iframe + pframe;
213 }
214 
215 static int daala_packet(AVFormatContext *s, int idx)
216 {
217  int seg, duration = 1;
218  struct ogg *ogg = s->priv_data;
219  struct ogg_stream *os = ogg->streams + idx;
220 
221  /*
222  * first packet handling: here we parse the duration of each packet in the
223  * first page and compare the total duration to the page granule to find the
224  * encoder delay and set the first timestamp
225  */
226 
227  if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
228  for (seg = os->segp; seg < os->nsegs; seg++)
229  if (os->segments[seg] < 255)
230  duration++;
231 
232  os->lastpts = os->lastdts = daala_gptopts(s, idx, os->granule, NULL) - duration;
233  if(s->streams[idx]->start_time == AV_NOPTS_VALUE) {
234  s->streams[idx]->start_time = os->lastpts;
235  if (s->streams[idx]->duration)
236  s->streams[idx]->duration -= s->streams[idx]->start_time;
237  }
238  }
239 
240  /* parse packet duration */
241  if (os->psize > 0)
242  os->pduration = 1;
243 
244  return 0;
245 }
246 
247 const struct ogg_codec ff_daala_codec = {
248  .name = "Daala",
249  .magic = "\200daala",
250  .magicsize = 6,
251  .header = daala_header,
252  .packet = daala_packet,
253  .gptopts = daala_gptopts,
254  .granule_is_start = 1,
255  .nb_header = 3,
256 };
#define NULL
Definition: coverity.c:32
const char * s
Definition: avisynth_c.h:768
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
Copyright (C) 2005 Michael Ahlberg, Måns Rullgård.
Definition: oggdec.h:31
unsigned int pflags
Definition: oggdec.h:67
const char * fmt
Definition: avisynth_c.h:769
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:67
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: utils.c:4560
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3980
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:956
int num
Numerator.
Definition: rational.h:59
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:133
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:252
int flags
Definition: oggdec.h:76
int64_t lastpts
Definition: oggdec.h:72
#define bytestream2_get_ne32
Definition: bytestream.h:117
Format I/O context.
Definition: avformat.h:1338
unsigned int psize
Definition: oggdec.h:66
uint8_t
int width
Video only.
Definition: avcodec.h:4046
struct DaalaPixFmtMap format
Definition: oggparsedaala.c:53
enum AVStreamParseType need_parsing
Definition: avformat.h:1076
static uint64_t daala_gptopts(AVFormatContext *ctx, int idx, uint64_t gp, int64_t *dts)
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1406
int64_t duration
Definition: movenc.c:63
int keyframe_granule_shift
Definition: oggparsedaala.c:52
#define av_log(a,...)
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1633
#define U(x)
Definition: vp56_arith.h:37
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
#define AVERROR(e)
Definition: error.h:43
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:164
int ff_vorbis_stream_comment(AVFormatContext *as, AVStream *st, const uint8_t *buf, int size)
#define OGG_FLAG_EOS
Definition: oggdec.h:112
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3976
uint8_t segments[255]
Definition: oggdec.h:80
int extradata_size
Size of the extradata content in bytes.
Definition: avcodec.h:3998
Only parse headers, do not repack.
Definition: avformat.h:811
uint64_t granule
Definition: oggdec.h:70
unsigned int pstart
Definition: oggdec.h:65
AVFormatContext * ctx
Definition: movenc.c:48
struct ogg_stream * streams
Definition: oggdec.h:102
int segp
Definition: oggdec.h:79
#define FF_ARRAY_ELEMS(a)
Stream structure.
Definition: avformat.h:889
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition: mem.c:187
unsigned int pduration
Definition: oggdec.h:68
int nsegs
Definition: oggdec.h:79
const int8_t * name
Definition: oggdec.h:34
enum AVPixelFormat ffmpeg_fmt
Definition: oggparsedaala.c:30
void * private
Definition: oggdec.h:90
Rational number (pair of numerator and denominator).
Definition: rational.h:58
int64_t lastdts
Definition: oggdec.h:73
static int daala_packet(AVFormatContext *s, int idx)
const struct ogg_codec ff_daala_codec
int64_t duration
Decoding: duration of the stream, in stream time base.
Definition: avformat.h:943
uint8_t * buf
Definition: oggdec.h:62
Main libavformat public API header.
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:62
int64_t start_time
Decoding: pts of the first frame of the stream in presentation order, in stream time base...
Definition: avformat.h:936
static int daala_match_pix_fmt(struct DaalaPixFmtMap *fmt)
Definition: oggparsedaala.c:56
int den
Denominator.
Definition: rational.h:60
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
Definition: avcodec.h:734
Definition: oggdec.h:101
void * priv_data
Format private data.
Definition: avformat.h:1366
static int daala_header(AVFormatContext *s, int idx)
Definition: oggparsedaala.c:78
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: avcodec.h:3994
uint8_t magicsize
Definition: oggdec.h:33
#define gp
Definition: regdef.h:62
AVCodecParameters * codecpar
Definition: avformat.h:1241
static const struct DaalaPixFmtMap list_fmts[]
Definition: oggparsedaala.c:38
AVPixelFormat
Pixel format.
Definition: pixfmt.h:60
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:242