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.

141 lines
4.2KB

  1. /*
  2. * AIX demuxer
  3. * Copyright (c) 2016 Paul B Mahol
  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 "avformat.h"
  23. #include "internal.h"
  24. static int aix_probe(AVProbeData *p)
  25. {
  26. if (AV_RL32(p->buf) != MKTAG('A','I','X','F') ||
  27. AV_RB32(p->buf + 8) != 0x01000014 ||
  28. AV_RB32(p->buf + 12) != 0x00000800)
  29. return 0;
  30. return AVPROBE_SCORE_MAX;
  31. }
  32. static int aix_read_header(AVFormatContext *s)
  33. {
  34. unsigned nb_streams, first_offset, nb_segments;
  35. unsigned stream_list_offset;
  36. unsigned segment_list_offset = 0x20;
  37. unsigned segment_list_entry_size = 0x10;
  38. unsigned size;
  39. int i;
  40. avio_skip(s->pb, 4);
  41. first_offset = avio_rb32(s->pb) + 8;
  42. avio_skip(s->pb, 16);
  43. nb_segments = avio_rb16(s->pb);
  44. if (nb_segments == 0)
  45. return AVERROR_INVALIDDATA;
  46. stream_list_offset = segment_list_offset + segment_list_entry_size * nb_segments + 0x10;
  47. if (stream_list_offset >= first_offset)
  48. return AVERROR_INVALIDDATA;
  49. avio_seek(s->pb, stream_list_offset, SEEK_SET);
  50. nb_streams = avio_r8(s->pb);
  51. if (nb_streams == 0)
  52. return AVERROR_INVALIDDATA;
  53. avio_skip(s->pb, 7);
  54. for (i = 0; i < nb_streams; i++) {
  55. AVStream *st = avformat_new_stream(s, NULL);
  56. if (!st)
  57. return AVERROR(ENOMEM);
  58. st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
  59. st->codecpar->codec_id = AV_CODEC_ID_ADPCM_ADX;
  60. st->codecpar->sample_rate = avio_rb32(s->pb);
  61. st->codecpar->channels = avio_r8(s->pb);
  62. avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
  63. avio_skip(s->pb, 3);
  64. }
  65. avio_seek(s->pb, first_offset, SEEK_SET);
  66. for (i = 0; i < nb_streams; i++) {
  67. if (avio_rl32(s->pb) != MKTAG('A','I','X','P'))
  68. return AVERROR_INVALIDDATA;
  69. size = avio_rb32(s->pb);
  70. if (size <= 8)
  71. return AVERROR_INVALIDDATA;
  72. avio_skip(s->pb, 8);
  73. ff_get_extradata(s->streams[i]->codecpar, s->pb, size - 8);
  74. }
  75. return 0;
  76. }
  77. static int aix_read_packet(AVFormatContext *s, AVPacket *pkt)
  78. {
  79. unsigned size, index, duration, chunk;
  80. int64_t pos;
  81. int sequence, ret, i;
  82. pos = avio_tell(s->pb);
  83. if (avio_feof(s->pb))
  84. return AVERROR_EOF;
  85. chunk = avio_rl32(s->pb);
  86. size = avio_rb32(s->pb);
  87. if (chunk == MKTAG('A','I','X','E')) {
  88. avio_skip(s->pb, size);
  89. for (i = 0; i < s->nb_streams; i++) {
  90. if (avio_feof(s->pb))
  91. return AVERROR_EOF;
  92. chunk = avio_rl32(s->pb);
  93. size = avio_rb32(s->pb);
  94. avio_skip(s->pb, size);
  95. }
  96. pos = avio_tell(s->pb);
  97. chunk = avio_rl32(s->pb);
  98. size = avio_rb32(s->pb);
  99. }
  100. if (chunk != MKTAG('A','I','X','P'))
  101. return AVERROR_INVALIDDATA;
  102. if (size <= 8)
  103. return AVERROR_INVALIDDATA;
  104. index = avio_r8(s->pb);
  105. if (avio_r8(s->pb) != s->nb_streams || index >= s->nb_streams)
  106. return AVERROR_INVALIDDATA;
  107. duration = avio_rb16(s->pb);
  108. sequence = avio_rb32(s->pb);
  109. if (sequence < 0) {
  110. avio_skip(s->pb, size - 8);
  111. return 0;
  112. }
  113. ret = av_get_packet(s->pb, pkt, size - 8);
  114. pkt->stream_index = index;
  115. pkt->duration = duration;
  116. pkt->pos = pos;
  117. return ret;
  118. }
  119. AVInputFormat ff_aix_demuxer = {
  120. .name = "aix",
  121. .long_name = NULL_IF_CONFIG_SMALL("CRI AIX"),
  122. .read_probe = aix_probe,
  123. .read_header = aix_read_header,
  124. .read_packet = aix_read_packet,
  125. .extensions = "aix",
  126. .flags = AVFMT_GENERIC_INDEX,
  127. };