mirror of https://github.com/FFmpeg/FFmpeg.git
The Xiph foundation never standardized either Daala nor its mapping in Ogg, and all files that were created are undecodable without knowledge of the git hash.pull/338/head
parent
88567a2e52
commit
9576e49b40
5 changed files with 0 additions and 265 deletions
@ -1,261 +0,0 @@ |
|||||||
/*
|
|
||||||
* Ogg Daala parser |
|
||||||
* Copyright (C) 2015 Rostislav Pehlivanov <atomnuker gmail com> |
|
||||||
* Copyright (C) 2015 Vittorio Giovara <vittorio.giovara gmail com> |
|
||||||
* |
|
||||||
* This file is part of FFmpeg. |
|
||||||
* |
|
||||||
* FFmpeg is free software; you can redistribute it and/or |
|
||||||
* modify it under the terms of the GNU Lesser General Public |
|
||||||
* License as published by the Free Software Foundation; either |
|
||||||
* version 2.1 of the License, or (at your option) any later version. |
|
||||||
* |
|
||||||
* FFmpeg is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
||||||
* Lesser General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU Lesser General Public |
|
||||||
* License along with FFmpeg; if not, write to the Free Software |
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <stdlib.h> |
|
||||||
#include "libavcodec/bytestream.h" |
|
||||||
#include "avformat.h" |
|
||||||
#include "internal.h" |
|
||||||
#include "oggdec.h" |
|
||||||
|
|
||||||
struct DaalaPixFmtMap { |
|
||||||
enum AVPixelFormat ffmpeg_fmt; |
|
||||||
int depth; |
|
||||||
int planes; |
|
||||||
int xdec[4]; |
|
||||||
int ydec[4]; |
|
||||||
}; |
|
||||||
|
|
||||||
/* Currently supported formats only */ |
|
||||||
static const struct DaalaPixFmtMap list_fmts[] = { |
|
||||||
{ AV_PIX_FMT_YUV420P, 8, 3, {0, 1, 1, 0}, {0, 1, 1, 0} }, |
|
||||||
{ AV_PIX_FMT_YUV444P, 8, 3, {0, 0, 0, 0}, {0, 0, 0, 0} } |
|
||||||
}; |
|
||||||
|
|
||||||
typedef struct DaalaInfoHeader { |
|
||||||
int init_d; |
|
||||||
int fpr; |
|
||||||
int gpshift; |
|
||||||
int gpmask; |
|
||||||
int version_maj; |
|
||||||
int version_min; |
|
||||||
int version_sub; |
|
||||||
int frame_duration; |
|
||||||
int keyframe_granule_shift; |
|
||||||
struct DaalaPixFmtMap format; |
|
||||||
} DaalaInfoHeader; |
|
||||||
|
|
||||||
static inline int daala_match_pix_fmt(struct DaalaPixFmtMap *fmt) |
|
||||||
{ |
|
||||||
int i, j; |
|
||||||
for (i = 0; i < FF_ARRAY_ELEMS(list_fmts); i++) { |
|
||||||
int match = 0; |
|
||||||
if (fmt->depth != list_fmts[i].depth) |
|
||||||
continue; |
|
||||||
if (fmt->planes != list_fmts[i].planes) |
|
||||||
continue; |
|
||||||
for (j = 0; j < fmt->planes; j++) { |
|
||||||
if (fmt->xdec[j] != list_fmts[i].xdec[j]) |
|
||||||
continue; |
|
||||||
if (fmt->ydec[j] != list_fmts[i].ydec[j]) |
|
||||||
continue; |
|
||||||
match++; |
|
||||||
} |
|
||||||
if (match == fmt->planes) |
|
||||||
return list_fmts[i].ffmpeg_fmt; |
|
||||||
} |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
static int daala_header(AVFormatContext *s, int idx) |
|
||||||
{ |
|
||||||
int i, err; |
|
||||||
uint8_t *cdp; |
|
||||||
GetByteContext gb; |
|
||||||
AVRational timebase; |
|
||||||
struct ogg *ogg = s->priv_data; |
|
||||||
struct ogg_stream *os = ogg->streams + idx; |
|
||||||
AVStream *st = s->streams[idx]; |
|
||||||
int cds = st->codecpar->extradata_size + os->psize + 2; |
|
||||||
DaalaInfoHeader *hdr = os->private; |
|
||||||
|
|
||||||
if (!(os->buf[os->pstart] & 0x80)) |
|
||||||
return 0; |
|
||||||
|
|
||||||
if (!hdr) { |
|
||||||
hdr = av_mallocz(sizeof(*hdr)); |
|
||||||
if (!hdr) |
|
||||||
return AVERROR(ENOMEM); |
|
||||||
os->private = hdr; |
|
||||||
} |
|
||||||
|
|
||||||
switch (os->buf[os->pstart]) { |
|
||||||
case 0x80: |
|
||||||
bytestream2_init(&gb, os->buf + os->pstart, os->psize); |
|
||||||
bytestream2_skip(&gb, ff_daala_codec.magicsize); |
|
||||||
|
|
||||||
hdr->version_maj = bytestream2_get_byte(&gb); |
|
||||||
hdr->version_min = bytestream2_get_byte(&gb); |
|
||||||
hdr->version_sub = bytestream2_get_byte(&gb); |
|
||||||
|
|
||||||
st->codecpar->width = bytestream2_get_ne32(&gb); |
|
||||||
st->codecpar->height = bytestream2_get_ne32(&gb); |
|
||||||
|
|
||||||
st->sample_aspect_ratio.num = bytestream2_get_ne32(&gb); |
|
||||||
st->sample_aspect_ratio.den = bytestream2_get_ne32(&gb); |
|
||||||
|
|
||||||
timebase.num = bytestream2_get_ne32(&gb); |
|
||||||
timebase.den = bytestream2_get_ne32(&gb); |
|
||||||
if (timebase.num < 0 && timebase.den < 0) { |
|
||||||
av_log(s, AV_LOG_WARNING, "Invalid timebase, assuming 30 FPS\n"); |
|
||||||
timebase.num = 1; |
|
||||||
timebase.den = 30; |
|
||||||
} |
|
||||||
avpriv_set_pts_info(st, 64, timebase.den, timebase.num); |
|
||||||
|
|
||||||
hdr->frame_duration = bytestream2_get_ne32(&gb); |
|
||||||
hdr->gpshift = bytestream2_get_byte(&gb); |
|
||||||
if (hdr->gpshift >= 32) { |
|
||||||
av_log(s, AV_LOG_ERROR, "Too large gpshift %d (>= 32).\n", |
|
||||||
hdr->gpshift); |
|
||||||
hdr->gpshift = 0; |
|
||||||
return AVERROR_INVALIDDATA; |
|
||||||
} |
|
||||||
hdr->gpmask = (1U << hdr->gpshift) - 1; |
|
||||||
|
|
||||||
hdr->format.depth = 8 + 2*(bytestream2_get_byte(&gb)-1); |
|
||||||
|
|
||||||
hdr->fpr = bytestream2_get_byte(&gb); |
|
||||||
|
|
||||||
hdr->format.planes = bytestream2_get_byte(&gb); |
|
||||||
if (hdr->format.planes > 4) { |
|
||||||
av_log(s, AV_LOG_ERROR, |
|
||||||
"Invalid number of planes %d in daala pixel format map.\n", |
|
||||||
hdr->format.planes); |
|
||||||
return AVERROR_INVALIDDATA; |
|
||||||
} |
|
||||||
for (i = 0; i < hdr->format.planes; i++) { |
|
||||||
hdr->format.xdec[i] = bytestream2_get_byte(&gb); |
|
||||||
hdr->format.ydec[i] = bytestream2_get_byte(&gb); |
|
||||||
} |
|
||||||
|
|
||||||
if ((st->codecpar->format = daala_match_pix_fmt(&hdr->format)) < 0) |
|
||||||
av_log(s, AV_LOG_ERROR, "Unsupported pixel format - %i %i\n", |
|
||||||
hdr->format.depth, hdr->format.planes); |
|
||||||
|
|
||||||
st->codecpar->codec_id = AV_CODEC_ID_DAALA; |
|
||||||
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; |
|
||||||
st->need_parsing = AVSTREAM_PARSE_HEADERS; |
|
||||||
|
|
||||||
hdr->init_d = 1; |
|
||||||
break; |
|
||||||
case 0x81: |
|
||||||
if (!hdr->init_d) |
|
||||||
return AVERROR_INVALIDDATA; |
|
||||||
ff_vorbis_stream_comment(s, st, |
|
||||||
os->buf + os->pstart + ff_daala_codec.magicsize, |
|
||||||
os->psize - ff_daala_codec.magicsize); |
|
||||||
break; |
|
||||||
case 0x82: |
|
||||||
if (!hdr->init_d) |
|
||||||
return AVERROR_INVALIDDATA; |
|
||||||
break; |
|
||||||
default: |
|
||||||
av_log(s, AV_LOG_ERROR, "Unknown header type %X\n", os->buf[os->pstart]); |
|
||||||
return AVERROR_INVALIDDATA; |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
if ((err = av_reallocp(&st->codecpar->extradata, |
|
||||||
cds + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) { |
|
||||||
st->codecpar->extradata_size = 0; |
|
||||||
return err; |
|
||||||
} |
|
||||||
|
|
||||||
memset(st->codecpar->extradata + cds, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
|
||||||
cdp = st->codecpar->extradata + st->codecpar->extradata_size; |
|
||||||
*cdp++ = os->psize >> 8; |
|
||||||
*cdp++ = os->psize & 0xff; |
|
||||||
memcpy(cdp, os->buf + os->pstart, os->psize); |
|
||||||
st->codecpar->extradata_size = cds; |
|
||||||
|
|
||||||
return 1; |
|
||||||
} |
|
||||||
|
|
||||||
static uint64_t daala_gptopts(AVFormatContext *ctx, int idx, uint64_t gp, |
|
||||||
int64_t *dts) |
|
||||||
{ |
|
||||||
uint64_t iframe, pframe; |
|
||||||
struct ogg *ogg = ctx->priv_data; |
|
||||||
struct ogg_stream *os = ogg->streams + idx; |
|
||||||
DaalaInfoHeader *hdr = os->private; |
|
||||||
|
|
||||||
if (!hdr) |
|
||||||
return AV_NOPTS_VALUE; |
|
||||||
|
|
||||||
iframe = gp >> hdr->gpshift; |
|
||||||
pframe = gp & hdr->gpmask; |
|
||||||
|
|
||||||
if (!pframe) |
|
||||||
os->pflags |= AV_PKT_FLAG_KEY; |
|
||||||
|
|
||||||
if (dts) |
|
||||||
*dts = iframe + pframe; |
|
||||||
|
|
||||||
return iframe + pframe; |
|
||||||
} |
|
||||||
|
|
||||||
static int daala_packet(AVFormatContext *s, int idx) |
|
||||||
{ |
|
||||||
int seg, duration = 1; |
|
||||||
struct ogg *ogg = s->priv_data; |
|
||||||
struct ogg_stream *os = ogg->streams + idx; |
|
||||||
int64_t pts; |
|
||||||
|
|
||||||
/*
|
|
||||||
* first packet handling: here we parse the duration of each packet in the |
|
||||||
* first page and compare the total duration to the page granule to find the |
|
||||||
* encoder delay and set the first timestamp |
|
||||||
*/ |
|
||||||
|
|
||||||
if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) { |
|
||||||
for (seg = os->segp; seg < os->nsegs; seg++) |
|
||||||
if (os->segments[seg] < 255) |
|
||||||
duration++; |
|
||||||
|
|
||||||
pts = daala_gptopts(s, idx, os->granule, NULL); |
|
||||||
if (pts != AV_NOPTS_VALUE) |
|
||||||
pts -= duration; |
|
||||||
os->lastpts = os->lastdts = pts; |
|
||||||
if(s->streams[idx]->start_time == AV_NOPTS_VALUE) { |
|
||||||
s->streams[idx]->start_time = os->lastpts; |
|
||||||
if (s->streams[idx]->duration != AV_NOPTS_VALUE) |
|
||||||
s->streams[idx]->duration -= s->streams[idx]->start_time; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* parse packet duration */ |
|
||||||
if (os->psize > 0) |
|
||||||
os->pduration = 1; |
|
||||||
|
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
const struct ogg_codec ff_daala_codec = { |
|
||||||
.name = "Daala", |
|
||||||
.magic = "\200daala", |
|
||||||
.magicsize = 6, |
|
||||||
.header = daala_header, |
|
||||||
.packet = daala_packet, |
|
||||||
.gptopts = daala_gptopts, |
|
||||||
.granule_is_start = 1, |
|
||||||
.nb_header = 3, |
|
||||||
}; |
|
Loading…
Reference in new issue