/libavformat/vocdec.c

http://github.com/FFmpeg/FFmpeg · C · 110 lines · 75 code · 14 blank · 21 comment · 13 complexity · 259d6ca96cdb11e7ac4d4a0da8f990f3 MD5 · raw file

  1. /*
  2. * Creative Voice File demuxer.
  3. * Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.org>
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include "libavutil/intreadwrite.h"
  22. #include "voc.h"
  23. #include "internal.h"
  24. static int voc_probe(const AVProbeData *p)
  25. {
  26. int version, check;
  27. if (memcmp(p->buf, ff_voc_magic, sizeof(ff_voc_magic) - 1))
  28. return 0;
  29. version = AV_RL16(p->buf + 22);
  30. check = AV_RL16(p->buf + 24);
  31. if (~version + 0x1234 != check)
  32. return 10;
  33. return AVPROBE_SCORE_MAX;
  34. }
  35. static int voc_read_header(AVFormatContext *s)
  36. {
  37. VocDecContext *voc = s->priv_data;
  38. AVIOContext *pb = s->pb;
  39. int header_size;
  40. avio_skip(pb, 20);
  41. header_size = avio_rl16(pb) - 22;
  42. if (header_size != 4) {
  43. av_log(s, AV_LOG_ERROR, "unknown header size: %d\n", header_size);
  44. return AVERROR(ENOSYS);
  45. }
  46. avio_skip(pb, header_size);
  47. s->ctx_flags |= AVFMTCTX_NOHEADER;
  48. voc->remaining_size = 0;
  49. return 0;
  50. }
  51. static int voc_read_packet(AVFormatContext *s, AVPacket *pkt)
  52. {
  53. if (!s->nb_streams) {
  54. AVStream *st = avformat_new_stream(s, NULL);
  55. if (!st)
  56. return AVERROR(ENOMEM);
  57. st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
  58. }
  59. return ff_voc_get_packet(s, pkt, s->streams[0], 0);
  60. }
  61. static int voc_read_seek(AVFormatContext *s, int stream_index,
  62. int64_t timestamp, int flags)
  63. {
  64. VocDecContext *voc = s->priv_data;
  65. AVStream *st;
  66. int index;
  67. if (s->nb_streams < 1) {
  68. av_log(s, AV_LOG_ERROR, "cannot seek while no stream was found yet\n");
  69. return AVERROR(EINVAL);
  70. }
  71. st = s->streams[stream_index];
  72. index = av_index_search_timestamp(st, timestamp, flags);
  73. if (index >= 0 && index < st->nb_index_entries - 1) {
  74. AVIndexEntry *e = &st->index_entries[index];
  75. avio_seek(s->pb, e->pos, SEEK_SET);
  76. voc->pts = e->timestamp;
  77. voc->remaining_size = e->size;
  78. return 0;
  79. } else if (st->nb_index_entries && st->index_entries[0].timestamp <= timestamp) {
  80. AVIndexEntry *e = &st->index_entries[st->nb_index_entries - 1];
  81. // prepare context for seek_frame_generic()
  82. voc->pts = e->timestamp;
  83. voc->remaining_size = e->size;
  84. }
  85. return -1;
  86. }
  87. AVInputFormat ff_voc_demuxer = {
  88. .name = "voc",
  89. .long_name = NULL_IF_CONFIG_SMALL("Creative Voice"),
  90. .priv_data_size = sizeof(VocDecContext),
  91. .read_probe = voc_probe,
  92. .read_header = voc_read_header,
  93. .read_packet = voc_read_packet,
  94. .read_seek = voc_read_seek,
  95. .codec_tag = (const AVCodecTag* const []){ ff_voc_codec_tags, 0 },
  96. };