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  hdr->gpshift = 0;
130  return AVERROR_INVALIDDATA;
131  }
132  hdr->gpmask = (1U << hdr->gpshift) - 1;
133 
134  hdr->format.depth = 8 + 2*(bytestream2_get_byte(&gb)-1);
135 
136  hdr->fpr = bytestream2_get_byte(&gb);
137 
138  hdr->format.planes = bytestream2_get_byte(&gb);
139  if (hdr->format.planes > 4) {
140  av_log(s, AV_LOG_ERROR,
141  "Invalid number of planes %d in daala pixel format map.\n",
142  hdr->format.planes);
143  return AVERROR_INVALIDDATA;
144  }
145  for (i = 0; i < hdr->format.planes; i++) {
146  hdr->format.xdec[i] = bytestream2_get_byte(&gb);
147  hdr->format.ydec[i] = bytestream2_get_byte(&gb);
148  }
149 
150  if ((st->codecpar->format = daala_match_pix_fmt(&hdr->format)) < 0)
151  av_log(s, AV_LOG_ERROR, "Unsupported pixel format - %i %i\n",
152  hdr->format.depth, hdr->format.planes);
153 
157 
158  hdr->init_d = 1;
159  break;
160  case 0x81:
161  if (!hdr->init_d)
162  return AVERROR_INVALIDDATA;
164  os->buf + os->pstart + ff_daala_codec.magicsize,
166  break;
167  case 0x82:
168  if (!hdr->init_d)
169  return AVERROR_INVALIDDATA;
170  break;
171  default:
172  av_log(s, AV_LOG_ERROR, "Unknown header type %X\n", os->buf[os->pstart]);
173  return AVERROR_INVALIDDATA;
174  break;
175  }
176 
177  if ((err = av_reallocp(&st->codecpar->extradata,
178  cds + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
179  st->codecpar->extradata_size = 0;
180  return err;
181  }
182 
183  memset(st->codecpar->extradata + cds, 0, AV_INPUT_BUFFER_PADDING_SIZE);
184  cdp = st->codecpar->extradata + st->codecpar->extradata_size;
185  *cdp++ = os->psize >> 8;
186  *cdp++ = os->psize & 0xff;
187  memcpy(cdp, os->buf + os->pstart, os->psize);
188  st->codecpar->extradata_size = cds;
189 
190  return 1;
191 }
192 
193 static uint64_t daala_gptopts(AVFormatContext *ctx, int idx, uint64_t gp,
194  int64_t *dts)
195 {
196  uint64_t iframe, pframe;
197  struct ogg *ogg = ctx->priv_data;
198  struct ogg_stream *os = ogg->streams + idx;
199  DaalaInfoHeader *hdr = os->private;
200 
201  if (!hdr)
202  return AV_NOPTS_VALUE;
203 
204  iframe = gp >> hdr->gpshift;
205  pframe = gp & hdr->gpmask;
206 
207  if (!pframe)
208  os->pflags |= AV_PKT_FLAG_KEY;
209 
210  if (dts)
211  *dts = iframe + pframe;
212 
213  return iframe + pframe;
214 }
215 
216 static int daala_packet(AVFormatContext *s, int idx)
217 {
218  int seg, duration = 1;
219  struct ogg *ogg = s->priv_data;
220  struct ogg_stream *os = ogg->streams + idx;
221  int64_t pts;
222 
223  /*
224  * first packet handling: here we parse the duration of each packet in the
225  * first page and compare the total duration to the page granule to find the
226  * encoder delay and set the first timestamp
227  */
228 
229  if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
230  for (seg = os->segp; seg < os->nsegs; seg++)
231  if (os->segments[seg] < 255)
232  duration++;
233 
234  pts = daala_gptopts(s, idx, os->granule, NULL);
235  if (pts != AV_NOPTS_VALUE)
236  pts -= duration;
237  os->lastpts = os->lastdts = pts;
238  if(s->streams[idx]->start_time == AV_NOPTS_VALUE) {
239  s->streams[idx]->start_time = os->lastpts;
240  if (s->streams[idx]->duration != AV_NOPTS_VALUE)
241  s->streams[idx]->duration -= s->streams[idx]->start_time;
242  }
243  }
244 
245  /* parse packet duration */
246  if (os->psize > 0)
247  os->pduration = 1;
248 
249  return 0;
250 }
251 
252 const struct ogg_codec ff_daala_codec = {
253  .name = "Daala",
254  .magic = "\200daala",
255  .magicsize = 6,
256  .header = daala_header,
257  .packet = daala_packet,
258  .gptopts = daala_gptopts,
259  .granule_is_start = 1,
260  .nb_header = 3,
261 };
#define NULL
Definition: coverity.c:32
#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:71
#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:4882
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3900
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:936
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:236
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:1351
unsigned int psize
Definition: oggdec.h:66
uint8_t
int width
Video only.
Definition: avcodec.h:3966
struct DaalaPixFmtMap format
Definition: oggparsedaala.c:53
enum AVStreamParseType need_parsing
Definition: avformat.h:1092
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:1419
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:1477
#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:3896
uint8_t segments[255]
Definition: oggdec.h:80
int extradata_size
Size of the extradata content in bytes.
Definition: avcodec.h:3918
Only parse headers, do not repack.
Definition: avformat.h:794
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 s(width, name)
Definition: cbs_vp9.c:257
#define FF_ARRAY_ELEMS(a)
Stream structure.
Definition: avformat.h:874
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:163
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 int64_t pts
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:923
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:66
int64_t start_time
Decoding: pts of the first frame of the stream in presentation order, in stream time base...
Definition: avformat.h:913
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:782
Definition: oggdec.h:101
void * priv_data
Format private data.
Definition: avformat.h:1379
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:3914
uint8_t magicsize
Definition: oggdec.h:33
#define gp
Definition: regdef.h:62
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1021
static const struct DaalaPixFmtMap list_fmts[]
Definition: oggparsedaala.c:38
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248