oggparsedaala.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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. #include <stdlib.h>
  23. #include "libavcodec/bytestream.h"
  24. #include "avformat.h"
  25. #include "internal.h"
  26. #include "oggdec.h"
  27. struct DaalaPixFmtMap {
  28. enum AVPixelFormat ffmpeg_fmt;
  29. int depth;
  30. int planes;
  31. int xdec[4];
  32. int ydec[4];
  33. };
  34. /* Currently supported formats only */
  35. static const struct DaalaPixFmtMap list_fmts[] = {
  36. { AV_PIX_FMT_YUV420P, 8, 3, {0, 1, 1, 0}, {0, 1, 1, 0} },
  37. { AV_PIX_FMT_YUV444P, 8, 3, {0, 0, 0, 0}, {0, 0, 0, 0} }
  38. };
  39. typedef struct DaalaInfoHeader {
  40. int init_d;
  41. int fpr;
  42. int gpshift;
  43. int gpmask;
  44. int version_maj;
  45. int version_min;
  46. int version_sub;
  47. int frame_duration;
  48. int keyframe_granule_shift;
  49. struct DaalaPixFmtMap format;
  50. } DaalaInfoHeader;
  51. static inline int daala_match_pix_fmt(struct DaalaPixFmtMap *fmt)
  52. {
  53. int i, j;
  54. for (i = 0; i < FF_ARRAY_ELEMS(list_fmts); i++) {
  55. int match = 0;
  56. if (fmt->depth != list_fmts[i].depth)
  57. continue;
  58. if (fmt->planes != list_fmts[i].planes)
  59. continue;
  60. for (j = 0; j < fmt->planes; j++) {
  61. if (fmt->xdec[j] != list_fmts[i].xdec[j])
  62. continue;
  63. if (fmt->ydec[j] != list_fmts[i].ydec[j])
  64. continue;
  65. match++;
  66. }
  67. if (match == fmt->planes)
  68. return list_fmts[i].ffmpeg_fmt;
  69. }
  70. return -1;
  71. }
  72. static int daala_header(AVFormatContext *s, int idx)
  73. {
  74. int i, err;
  75. uint8_t *cdp;
  76. GetByteContext gb;
  77. AVRational timebase;
  78. struct ogg *ogg = s->priv_data;
  79. struct ogg_stream *os = ogg->streams + idx;
  80. AVStream *st = s->streams[idx];
  81. int cds = st->codecpar->extradata_size + os->psize + 2;
  82. DaalaInfoHeader *hdr = os->private;
  83. if (!(os->buf[os->pstart] & 0x80))
  84. return 0;
  85. if (!hdr) {
  86. hdr = av_mallocz(sizeof(*hdr));
  87. if (!hdr)
  88. return AVERROR(ENOMEM);
  89. os->private = hdr;
  90. }
  91. switch (os->buf[os->pstart]) {
  92. case 0x80:
  93. bytestream2_init(&gb, os->buf + os->pstart, os->psize);
  94. bytestream2_skip(&gb, ff_daala_codec.magicsize);
  95. hdr->version_maj = bytestream2_get_byte(&gb);
  96. hdr->version_min = bytestream2_get_byte(&gb);
  97. hdr->version_sub = bytestream2_get_byte(&gb);
  98. st->codecpar->width = bytestream2_get_ne32(&gb);
  99. st->codecpar->height = bytestream2_get_ne32(&gb);
  100. st->sample_aspect_ratio.num = bytestream2_get_ne32(&gb);
  101. st->sample_aspect_ratio.den = bytestream2_get_ne32(&gb);
  102. timebase.num = bytestream2_get_ne32(&gb);
  103. timebase.den = bytestream2_get_ne32(&gb);
  104. if (timebase.num < 0 && timebase.den < 0) {
  105. av_log(s, AV_LOG_WARNING, "Invalid timebase, assuming 30 FPS\n");
  106. timebase.num = 1;
  107. timebase.den = 30;
  108. }
  109. avpriv_set_pts_info(st, 64, timebase.den, timebase.num);
  110. hdr->frame_duration = bytestream2_get_ne32(&gb);
  111. hdr->gpshift = bytestream2_get_byte(&gb);
  112. if (hdr->gpshift >= 32) {
  113. av_log(s, AV_LOG_ERROR, "Too large gpshift %d (>= 32).\n",
  114. hdr->gpshift);
  115. hdr->gpshift = 0;
  116. return AVERROR_INVALIDDATA;
  117. }
  118. hdr->gpmask = (1U << hdr->gpshift) - 1;
  119. hdr->format.depth = 8 + 2*(bytestream2_get_byte(&gb)-1);
  120. hdr->fpr = bytestream2_get_byte(&gb);
  121. hdr->format.planes = bytestream2_get_byte(&gb);
  122. if (hdr->format.planes > 4) {
  123. av_log(s, AV_LOG_ERROR,
  124. "Invalid number of planes %d in daala pixel format map.\n",
  125. hdr->format.planes);
  126. return AVERROR_INVALIDDATA;
  127. }
  128. for (i = 0; i < hdr->format.planes; i++) {
  129. hdr->format.xdec[i] = bytestream2_get_byte(&gb);
  130. hdr->format.ydec[i] = bytestream2_get_byte(&gb);
  131. }
  132. if ((st->codecpar->format = daala_match_pix_fmt(&hdr->format)) < 0)
  133. av_log(s, AV_LOG_ERROR, "Unsupported pixel format - %i %i\n",
  134. hdr->format.depth, hdr->format.planes);
  135. st->codecpar->codec_id = AV_CODEC_ID_DAALA;
  136. st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
  137. st->need_parsing = AVSTREAM_PARSE_HEADERS;
  138. hdr->init_d = 1;
  139. break;
  140. case 0x81:
  141. if (!hdr->init_d)
  142. return AVERROR_INVALIDDATA;
  143. ff_vorbis_stream_comment(s, st,
  144. os->buf + os->pstart + ff_daala_codec.magicsize,
  145. os->psize - ff_daala_codec.magicsize);
  146. break;
  147. case 0x82:
  148. if (!hdr->init_d)
  149. return AVERROR_INVALIDDATA;
  150. break;
  151. default:
  152. av_log(s, AV_LOG_ERROR, "Unknown header type %X\n", os->buf[os->pstart]);
  153. return AVERROR_INVALIDDATA;
  154. break;
  155. }
  156. if ((err = av_reallocp(&st->codecpar->extradata,
  157. cds + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
  158. st->codecpar->extradata_size = 0;
  159. return err;
  160. }
  161. memset(st->codecpar->extradata + cds, 0, AV_INPUT_BUFFER_PADDING_SIZE);
  162. cdp = st->codecpar->extradata + st->codecpar->extradata_size;
  163. *cdp++ = os->psize >> 8;
  164. *cdp++ = os->psize & 0xff;
  165. memcpy(cdp, os->buf + os->pstart, os->psize);
  166. st->codecpar->extradata_size = cds;
  167. return 1;
  168. }
  169. static uint64_t daala_gptopts(AVFormatContext *ctx, int idx, uint64_t gp,
  170. int64_t *dts)
  171. {
  172. uint64_t iframe, pframe;
  173. struct ogg *ogg = ctx->priv_data;
  174. struct ogg_stream *os = ogg->streams + idx;
  175. DaalaInfoHeader *hdr = os->private;
  176. if (!hdr)
  177. return AV_NOPTS_VALUE;
  178. iframe = gp >> hdr->gpshift;
  179. pframe = gp & hdr->gpmask;
  180. if (!pframe)
  181. os->pflags |= AV_PKT_FLAG_KEY;
  182. if (dts)
  183. *dts = iframe + pframe;
  184. return iframe + pframe;
  185. }
  186. static int daala_packet(AVFormatContext *s, int idx)
  187. {
  188. int seg, duration = 1;
  189. struct ogg *ogg = s->priv_data;
  190. struct ogg_stream *os = ogg->streams + idx;
  191. /*
  192. * first packet handling: here we parse the duration of each packet in the
  193. * first page and compare the total duration to the page granule to find the
  194. * encoder delay and set the first timestamp
  195. */
  196. if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
  197. for (seg = os->segp; seg < os->nsegs; seg++)
  198. if (os->segments[seg] < 255)
  199. duration++;
  200. os->lastpts = os->lastdts = daala_gptopts(s, idx, os->granule, NULL) - duration;
  201. if(s->streams[idx]->start_time == AV_NOPTS_VALUE) {
  202. s->streams[idx]->start_time = os->lastpts;
  203. if (s->streams[idx]->duration != AV_NOPTS_VALUE)
  204. s->streams[idx]->duration -= s->streams[idx]->start_time;
  205. }
  206. }
  207. /* parse packet duration */
  208. if (os->psize > 0)
  209. os->pduration = 1;
  210. return 0;
  211. }
  212. const struct ogg_codec ff_daala_codec = {
  213. .name = "Daala",
  214. .magic = "\200daala",
  215. .magicsize = 6,
  216. .header = daala_header,
  217. .packet = daala_packet,
  218. .gptopts = daala_gptopts,
  219. .granule_is_start = 1,
  220. .nb_header = 3,
  221. };