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.

307 lines
8.7KB

  1. /*
  2. * LEGO Racers ALP (.tun & .pcm) (de)muxer
  3. *
  4. * Copyright (C) 2020 Zane van Iperen (zane@zanevaniperen.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 "avformat.h"
  23. #include "internal.h"
  24. #include "rawenc.h"
  25. #include "libavutil/intreadwrite.h"
  26. #include "libavutil/internal.h"
  27. #include "libavutil/opt.h"
  28. #define ALP_TAG MKTAG('A', 'L', 'P', ' ')
  29. #define ALP_MAX_READ_SIZE 4096
  30. typedef struct ALPHeader {
  31. uint32_t magic; /*< Magic Number, {'A', 'L', 'P', ' '} */
  32. uint32_t header_size; /*< Header size (after this). */
  33. char adpcm[6]; /*< "ADPCM" */
  34. uint8_t unk1; /*< Unknown */
  35. uint8_t num_channels; /*< Channel Count. */
  36. uint32_t sample_rate; /*< Sample rate, only if header_size >= 12. */
  37. } ALPHeader;
  38. typedef enum ALPType {
  39. ALP_TYPE_AUTO = 0, /*< Autodetect based on file extension. */
  40. ALP_TYPE_TUN = 1, /*< Force a .TUN file. */
  41. ALP_TYPE_PCM = 2, /*< Force a .PCM file. */
  42. } ALPType;
  43. typedef struct ALPMuxContext {
  44. const AVClass *class;
  45. ALPType type;
  46. } ALPMuxContext;
  47. #if CONFIG_ALP_DEMUXER
  48. static int alp_probe(const AVProbeData *p)
  49. {
  50. uint32_t i;
  51. if (AV_RL32(p->buf) != ALP_TAG)
  52. return 0;
  53. /* Only allowed header sizes are 8 and 12. */
  54. i = AV_RL32(p->buf + 4);
  55. if (i != 8 && i != 12)
  56. return 0;
  57. if (strncmp("ADPCM", p->buf + 8, 6) != 0)
  58. return 0;
  59. return AVPROBE_SCORE_MAX - 1;
  60. }
  61. static int alp_read_header(AVFormatContext *s)
  62. {
  63. int ret;
  64. AVStream *st;
  65. ALPHeader *hdr = s->priv_data;
  66. AVCodecParameters *par;
  67. if ((hdr->magic = avio_rl32(s->pb)) != ALP_TAG)
  68. return AVERROR_INVALIDDATA;
  69. hdr->header_size = avio_rl32(s->pb);
  70. if (hdr->header_size != 8 && hdr->header_size != 12) {
  71. return AVERROR_INVALIDDATA;
  72. }
  73. if ((ret = avio_read(s->pb, hdr->adpcm, sizeof(hdr->adpcm))) < 0)
  74. return ret;
  75. else if (ret != sizeof(hdr->adpcm))
  76. return AVERROR(EIO);
  77. if (strncmp("ADPCM", hdr->adpcm, sizeof(hdr->adpcm)) != 0)
  78. return AVERROR_INVALIDDATA;
  79. hdr->unk1 = avio_r8(s->pb);
  80. hdr->num_channels = avio_r8(s->pb);
  81. if (hdr->header_size == 8) {
  82. /* .TUN music file */
  83. hdr->sample_rate = 22050;
  84. } else {
  85. /* .PCM sound file */
  86. hdr->sample_rate = avio_rl32(s->pb);
  87. }
  88. if (hdr->sample_rate > 44100) {
  89. avpriv_request_sample(s, "Sample Rate > 44100");
  90. return AVERROR_PATCHWELCOME;
  91. }
  92. if (!(st = avformat_new_stream(s, NULL)))
  93. return AVERROR(ENOMEM);
  94. par = st->codecpar;
  95. par->codec_type = AVMEDIA_TYPE_AUDIO;
  96. par->codec_id = AV_CODEC_ID_ADPCM_IMA_ALP;
  97. par->format = AV_SAMPLE_FMT_S16;
  98. par->sample_rate = hdr->sample_rate;
  99. par->channels = hdr->num_channels;
  100. if (hdr->num_channels == 1)
  101. par->channel_layout = AV_CH_LAYOUT_MONO;
  102. else if (hdr->num_channels == 2)
  103. par->channel_layout = AV_CH_LAYOUT_STEREO;
  104. else
  105. return AVERROR_INVALIDDATA;
  106. par->bits_per_coded_sample = 4;
  107. par->bits_per_raw_sample = 16;
  108. par->block_align = 1;
  109. par->bit_rate = par->channels *
  110. par->sample_rate *
  111. par->bits_per_coded_sample;
  112. avpriv_set_pts_info(st, 64, 1, par->sample_rate);
  113. return 0;
  114. }
  115. static int alp_read_packet(AVFormatContext *s, AVPacket *pkt)
  116. {
  117. int ret;
  118. AVCodecParameters *par = s->streams[0]->codecpar;
  119. if ((ret = av_get_packet(s->pb, pkt, ALP_MAX_READ_SIZE)) < 0)
  120. return ret;
  121. pkt->flags &= ~AV_PKT_FLAG_CORRUPT;
  122. pkt->stream_index = 0;
  123. pkt->duration = ret * 2 / par->channels;
  124. return 0;
  125. }
  126. static int alp_seek(AVFormatContext *s, int stream_index,
  127. int64_t pts, int flags)
  128. {
  129. const ALPHeader *hdr = s->priv_data;
  130. if (pts != 0)
  131. return AVERROR(EINVAL);
  132. return avio_seek(s->pb, hdr->header_size + 8, SEEK_SET);
  133. }
  134. AVInputFormat ff_alp_demuxer = {
  135. .name = "alp",
  136. .long_name = NULL_IF_CONFIG_SMALL("LEGO Racers ALP"),
  137. .priv_data_size = sizeof(ALPHeader),
  138. .read_probe = alp_probe,
  139. .read_header = alp_read_header,
  140. .read_packet = alp_read_packet,
  141. .read_seek = alp_seek,
  142. };
  143. #endif
  144. #if CONFIG_ALP_MUXER
  145. static int alp_write_init(AVFormatContext *s)
  146. {
  147. ALPMuxContext *alp = s->priv_data;
  148. AVCodecParameters *par;
  149. if (alp->type == ALP_TYPE_AUTO) {
  150. if (av_match_ext(s->url, "pcm"))
  151. alp->type = ALP_TYPE_PCM;
  152. else
  153. alp->type = ALP_TYPE_TUN;
  154. }
  155. if (s->nb_streams != 1) {
  156. av_log(s, AV_LOG_ERROR, "Too many streams\n");
  157. return AVERROR(EINVAL);
  158. }
  159. par = s->streams[0]->codecpar;
  160. if (par->codec_id != AV_CODEC_ID_ADPCM_IMA_ALP) {
  161. av_log(s, AV_LOG_ERROR, "%s codec not supported\n",
  162. avcodec_get_name(par->codec_id));
  163. return AVERROR(EINVAL);
  164. }
  165. if (par->channels > 2) {
  166. av_log(s, AV_LOG_ERROR, "A maximum of 2 channels are supported\n");
  167. return AVERROR(EINVAL);
  168. }
  169. if (par->sample_rate > 44100) {
  170. av_log(s, AV_LOG_ERROR, "Sample rate too large\n");
  171. return AVERROR(EINVAL);
  172. }
  173. if (alp->type == ALP_TYPE_TUN && par->sample_rate != 22050) {
  174. av_log(s, AV_LOG_ERROR, "Sample rate must be 22050 for TUN files\n");
  175. return AVERROR(EINVAL);
  176. }
  177. return 0;
  178. }
  179. static int alp_write_header(AVFormatContext *s)
  180. {
  181. ALPMuxContext *alp = s->priv_data;
  182. AVCodecParameters *par = s->streams[0]->codecpar;
  183. avio_wl32(s->pb, ALP_TAG);
  184. avio_wl32(s->pb, alp->type == ALP_TYPE_PCM ? 12 : 8);
  185. avio_write(s->pb, "ADPCM", 6);
  186. avio_w8(s->pb, 0);
  187. avio_w8(s->pb, par->channels);
  188. if (alp->type == ALP_TYPE_PCM)
  189. avio_wl32(s->pb, par->sample_rate);
  190. return 0;
  191. }
  192. enum { AE = AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM };
  193. static const AVOption alp_options[] = {
  194. {
  195. .name = "type",
  196. .help = "set file type",
  197. .offset = offsetof(ALPMuxContext, type),
  198. .type = AV_OPT_TYPE_INT,
  199. .default_val = {.i64 = ALP_TYPE_AUTO},
  200. .min = ALP_TYPE_AUTO,
  201. .max = ALP_TYPE_PCM,
  202. .flags = AE,
  203. .unit = "type",
  204. },
  205. {
  206. .name = "auto",
  207. .help = "autodetect based on file extension",
  208. .offset = 0,
  209. .type = AV_OPT_TYPE_CONST,
  210. .default_val = {.i64 = ALP_TYPE_AUTO},
  211. .min = 0,
  212. .max = 0,
  213. .flags = AE,
  214. .unit = "type"
  215. },
  216. {
  217. .name = "tun",
  218. .help = "force .tun, used for music",
  219. .offset = 0,
  220. .type = AV_OPT_TYPE_CONST,
  221. .default_val = {.i64 = ALP_TYPE_TUN},
  222. .min = 0,
  223. .max = 0,
  224. .flags = AE,
  225. .unit = "type"
  226. },
  227. {
  228. .name = "pcm",
  229. .help = "force .pcm, used for sfx",
  230. .offset = 0,
  231. .type = AV_OPT_TYPE_CONST,
  232. .default_val = {.i64 = ALP_TYPE_PCM},
  233. .min = 0,
  234. .max = 0,
  235. .flags = AE,
  236. .unit = "type"
  237. },
  238. { NULL }
  239. };
  240. static const AVClass alp_muxer_class = {
  241. .class_name = "alp",
  242. .item_name = av_default_item_name,
  243. .option = alp_options,
  244. .version = LIBAVUTIL_VERSION_INT
  245. };
  246. AVOutputFormat ff_alp_muxer = {
  247. .name = "alp",
  248. .long_name = NULL_IF_CONFIG_SMALL("LEGO Racers ALP"),
  249. .extensions = "tun,pcm",
  250. .audio_codec = AV_CODEC_ID_ADPCM_IMA_ALP,
  251. .video_codec = AV_CODEC_ID_NONE,
  252. .init = alp_write_init,
  253. .write_header = alp_write_header,
  254. .write_packet = ff_raw_write_packet,
  255. .priv_class = &alp_muxer_class,
  256. .priv_data_size = sizeof(ALPMuxContext)
  257. };
  258. #endif