You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
3.8KB

  1. /*
  2. * Copyright (C) 2008 David Conrad
  3. *
  4. * This file is part of Libav.
  5. *
  6. * Libav is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * Libav is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with Libav; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. #include "libavutil/intreadwrite.h"
  21. #include "libavcodec/dirac.h"
  22. #include "avformat.h"
  23. #include "internal.h"
  24. #include "oggdec.h"
  25. static int dirac_header(AVFormatContext *s, int idx)
  26. {
  27. struct ogg *ogg = s->priv_data;
  28. struct ogg_stream *os = ogg->streams + idx;
  29. AVStream *st = s->streams[idx];
  30. AVDiracSeqHeader *dsh;
  31. int ret;
  32. // already parsed the header
  33. if (st->codecpar->codec_id == AV_CODEC_ID_DIRAC)
  34. return 0;
  35. ret = av_dirac_parse_sequence_header(&dsh, os->buf + os->pstart + 13, (os->psize - 13) * 8, s);
  36. if (ret < 0)
  37. return ret;
  38. st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
  39. st->codecpar->codec_id = AV_CODEC_ID_DIRAC;
  40. st->codecpar->width = dsh->width;
  41. st->codecpar->height = dsh->height;
  42. st->codecpar->format = dsh->pix_fmt;
  43. st->codecpar->color_range = dsh->color_range;
  44. st->codecpar->color_trc = dsh->color_trc;
  45. st->codecpar->color_primaries = dsh->color_primaries;
  46. st->codecpar->color_space = dsh->colorspace;
  47. st->codecpar->profile = dsh->profile;
  48. st->codecpar->level = dsh->level;
  49. // Dirac in Ogg always stores timestamps as though the video were interlaced
  50. avpriv_set_pts_info(st, 64, dsh->framerate.den, 2 * dsh->framerate.num);
  51. av_freep(&dsh);
  52. return 1;
  53. }
  54. // various undocumented things: granule is signed (only for Dirac!)
  55. static uint64_t dirac_gptopts(AVFormatContext *s, int idx, uint64_t granule,
  56. int64_t *dts_out)
  57. {
  58. int64_t gp = granule;
  59. struct ogg *ogg = s->priv_data;
  60. struct ogg_stream *os = ogg->streams + idx;
  61. unsigned dist = ((gp >> 14) & 0xff00) | (gp & 0xff);
  62. int64_t dts = (gp >> 31);
  63. int64_t pts = dts + ((gp >> 9) & 0x1fff);
  64. if (!dist)
  65. os->pflags |= AV_PKT_FLAG_KEY;
  66. if (dts_out)
  67. *dts_out = dts;
  68. return pts;
  69. }
  70. static int old_dirac_header(AVFormatContext *s, int idx)
  71. {
  72. struct ogg *ogg = s->priv_data;
  73. struct ogg_stream *os = ogg->streams + idx;
  74. AVStream *st = s->streams[idx];
  75. uint8_t *buf = os->buf + os->pstart;
  76. if (buf[0] != 'K')
  77. return 0;
  78. st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
  79. st->codecpar->codec_id = AV_CODEC_ID_DIRAC;
  80. avpriv_set_pts_info(st, 64, AV_RB32(buf+12), AV_RB32(buf+8));
  81. return 1;
  82. }
  83. static uint64_t old_dirac_gptopts(AVFormatContext *s, int idx, uint64_t gp,
  84. int64_t *dts)
  85. {
  86. struct ogg *ogg = s->priv_data;
  87. struct ogg_stream *os = ogg->streams + idx;
  88. uint64_t iframe = gp >> 30;
  89. uint64_t pframe = gp & 0x3fffffff;
  90. if (!pframe)
  91. os->pflags |= AV_PKT_FLAG_KEY;
  92. return iframe + pframe;
  93. }
  94. const struct ogg_codec ff_dirac_codec = {
  95. .magic = "BBCD\0",
  96. .magicsize = 5,
  97. .header = dirac_header,
  98. .gptopts = dirac_gptopts,
  99. .granule_is_start = 1,
  100. .nb_header = 1,
  101. };
  102. const struct ogg_codec ff_old_dirac_codec = {
  103. .magic = "KW-DIRAC",
  104. .magicsize = 8,
  105. .header = old_dirac_header,
  106. .gptopts = old_dirac_gptopts,
  107. .granule_is_start = 1,
  108. .nb_header = 1,
  109. };