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.

300 lines
11KB

  1. /*
  2. * Tracked MOD demuxer (libopenmpt)
  3. * Copyright (c) 2016 Josh de Kock
  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 <libopenmpt/libopenmpt.h>
  22. #include <libopenmpt/libopenmpt_stream_callbacks_file.h>
  23. #include <libopenmpt/libopenmpt_version.h>
  24. /* Shims to support libopenmpt < 0.3.0 (as documented by libopenmpt) */
  25. #if !defined(OPENMPT_API_VERSION_MAKE)
  26. #define OPENMPT_API_VERSION_MAKE(major, minor, patch) (((major)<<24)|((minor)<<16)|((patch)<<0))
  27. #endif
  28. #if !defined(OPENMPT_API_VERSION_AT_LEAST)
  29. #define OPENMPT_API_VERSION_AT_LEAST(major, minor, patch) (OPENMPT_API_VERSION >= OPENMPT_API_VERSION_MAKE((major), (minor), (patch)))
  30. #endif
  31. #include "libavutil/avstring.h"
  32. #include "libavutil/opt.h"
  33. #include "avformat.h"
  34. #include "internal.h"
  35. typedef struct OpenMPTContext {
  36. const AVClass *class;
  37. openmpt_module *module;
  38. int channels;
  39. double duration;
  40. /* options */
  41. int sample_rate;
  42. int64_t layout;
  43. int subsong;
  44. } OpenMPTContext;
  45. #define OFFSET(x) offsetof(OpenMPTContext, x)
  46. #define A AV_OPT_FLAG_AUDIO_PARAM
  47. #define D AV_OPT_FLAG_DECODING_PARAM
  48. static const AVOption options[] = {
  49. { "sample_rate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, { .i64 = 48000 }, 1000, INT_MAX, A | D },
  50. { "layout", "set channel layout", OFFSET(layout), AV_OPT_TYPE_CHANNEL_LAYOUT, { .i64 = AV_CH_LAYOUT_STEREO }, 0, INT64_MAX, A | D },
  51. { "subsong", "set subsong", OFFSET(subsong), AV_OPT_TYPE_INT, { .i64 = -2 }, -2, INT_MAX, A | D, "subsong"},
  52. { "all", "all", 0, AV_OPT_TYPE_CONST, { .i64 = -1}, 0, 0, A | D, "subsong" },
  53. { "auto", "auto", 0, AV_OPT_TYPE_CONST, { .i64 = -2}, 0, 0, A | D, "subsong" },
  54. { NULL }
  55. };
  56. static void openmpt_logfunc(const char *message, void *userdata)
  57. {
  58. int level = AV_LOG_INFO;
  59. if (strstr(message, "ERROR") != NULL) {
  60. level = AV_LOG_ERROR;
  61. }
  62. av_log(userdata, level, "%s\n", message);
  63. }
  64. #define add_meta(s, name, meta) \
  65. do { \
  66. const char *value = meta; \
  67. if (value && value[0]) \
  68. av_dict_set(&s->metadata, name, value, 0); \
  69. openmpt_free_string(value); \
  70. } while(0)
  71. static int read_header_openmpt(AVFormatContext *s)
  72. {
  73. AVStream *st;
  74. OpenMPTContext *openmpt = s->priv_data;
  75. int64_t size;
  76. char *buf;
  77. #if OPENMPT_API_VERSION_AT_LEAST(0,3,0)
  78. int error;
  79. #endif
  80. int ret;
  81. size = avio_size(s->pb);
  82. if (size <= 0)
  83. return AVERROR_INVALIDDATA;
  84. buf = av_malloc(size);
  85. if (!buf)
  86. return AVERROR(ENOMEM);
  87. size = avio_read(s->pb, buf, size);
  88. if (size < 0) {
  89. av_log(s, AV_LOG_ERROR, "Reading input buffer failed.\n");
  90. av_freep(&buf);
  91. return size;
  92. }
  93. #if OPENMPT_API_VERSION_AT_LEAST(0,3,0)
  94. error = OPENMPT_ERROR_OK;
  95. openmpt->module = openmpt_module_create_from_memory2(buf, size, openmpt_logfunc, s, NULL, NULL, &error, NULL, NULL);
  96. av_freep(&buf);
  97. if (!openmpt->module) {
  98. if (error == OPENMPT_ERROR_OUT_OF_MEMORY)
  99. return AVERROR(ENOMEM);
  100. else if (error >= OPENMPT_ERROR_GENERAL)
  101. return AVERROR_INVALIDDATA;
  102. else
  103. return AVERROR_UNKNOWN;
  104. }
  105. #else
  106. openmpt->module = openmpt_module_create_from_memory(buf, size, openmpt_logfunc, s, NULL);
  107. av_freep(&buf);
  108. if (!openmpt->module)
  109. return AVERROR_INVALIDDATA;
  110. #endif
  111. openmpt->channels = av_get_channel_layout_nb_channels(openmpt->layout);
  112. if (openmpt->subsong >= openmpt_module_get_num_subsongs(openmpt->module)) {
  113. openmpt_module_destroy(openmpt->module);
  114. av_log(s, AV_LOG_ERROR, "Invalid subsong index: %d\n", openmpt->subsong);
  115. return AVERROR(EINVAL);
  116. }
  117. if (openmpt->subsong != -2) {
  118. if (openmpt->subsong >= 0) {
  119. av_dict_set_int(&s->metadata, "track", openmpt->subsong + 1, 0);
  120. }
  121. ret = openmpt_module_select_subsong(openmpt->module, openmpt->subsong);
  122. if (!ret){
  123. openmpt_module_destroy(openmpt->module);
  124. av_log(s, AV_LOG_ERROR, "Could not select requested subsong: %d", openmpt->subsong);
  125. return AVERROR(EINVAL);
  126. }
  127. }
  128. openmpt->duration = openmpt_module_get_duration_seconds(openmpt->module);
  129. add_meta(s, "artist", openmpt_module_get_metadata(openmpt->module, "artist"));
  130. add_meta(s, "title", openmpt_module_get_metadata(openmpt->module, "title"));
  131. add_meta(s, "encoder", openmpt_module_get_metadata(openmpt->module, "tracker"));
  132. add_meta(s, "comment", openmpt_module_get_metadata(openmpt->module, "message"));
  133. add_meta(s, "date", openmpt_module_get_metadata(openmpt->module, "date"));
  134. st = avformat_new_stream(s, NULL);
  135. if (!st) {
  136. openmpt_module_destroy(openmpt->module);
  137. openmpt->module = NULL;
  138. return AVERROR(ENOMEM);
  139. }
  140. avpriv_set_pts_info(st, 64, 1, AV_TIME_BASE);
  141. st->duration = llrint(openmpt->duration*AV_TIME_BASE);
  142. st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
  143. st->codecpar->codec_id = AV_NE(AV_CODEC_ID_PCM_F32BE, AV_CODEC_ID_PCM_F32LE);
  144. st->codecpar->channels = openmpt->channels;
  145. st->codecpar->sample_rate = openmpt->sample_rate;
  146. return 0;
  147. }
  148. #define AUDIO_PKT_SIZE 2048
  149. static int read_packet_openmpt(AVFormatContext *s, AVPacket *pkt)
  150. {
  151. OpenMPTContext *openmpt = s->priv_data;
  152. int n_samples = AUDIO_PKT_SIZE / (openmpt->channels ? openmpt->channels*4 : 4);
  153. int ret;
  154. if ((ret = av_new_packet(pkt, AUDIO_PKT_SIZE)) < 0)
  155. return ret;
  156. switch (openmpt->channels) {
  157. case 1:
  158. ret = openmpt_module_read_float_mono(openmpt->module, openmpt->sample_rate,
  159. n_samples, (float *)pkt->data);
  160. break;
  161. case 2:
  162. ret = openmpt_module_read_interleaved_float_stereo(openmpt->module, openmpt->sample_rate,
  163. n_samples, (float *)pkt->data);
  164. break;
  165. case 4:
  166. ret = openmpt_module_read_interleaved_float_quad(openmpt->module, openmpt->sample_rate,
  167. n_samples, (float *)pkt->data);
  168. break;
  169. default:
  170. av_log(s, AV_LOG_ERROR, "Unsupported number of channels: %d", openmpt->channels);
  171. return AVERROR(EINVAL);
  172. }
  173. if (ret < 1) {
  174. pkt->size = 0;
  175. return AVERROR_EOF;
  176. }
  177. pkt->size = ret * (openmpt->channels * 4);
  178. return 0;
  179. }
  180. static int read_close_openmpt(AVFormatContext *s)
  181. {
  182. OpenMPTContext *openmpt = s->priv_data;
  183. openmpt_module_destroy(openmpt->module);
  184. openmpt->module = NULL;
  185. return 0;
  186. }
  187. static int read_seek_openmpt(AVFormatContext *s, int stream_idx, int64_t ts, int flags)
  188. {
  189. OpenMPTContext *openmpt = s->priv_data;
  190. openmpt_module_set_position_seconds(openmpt->module, (double)ts/AV_TIME_BASE);
  191. return 0;
  192. }
  193. static int probe_openmpt_extension(AVProbeData *p)
  194. {
  195. const char *ext;
  196. if (p->filename) {
  197. ext = strrchr(p->filename, '.');
  198. if (ext && strlen(ext + 1) > 0) {
  199. ext++; /* skip '.' */
  200. if (openmpt_is_extension_supported(ext) == 1)
  201. return AVPROBE_SCORE_EXTENSION;
  202. }
  203. }
  204. return 0;
  205. }
  206. static int read_probe_openmpt(const AVProbeData *p)
  207. {
  208. #if OPENMPT_API_VERSION_AT_LEAST(0,3,0)
  209. int probe_result;
  210. if (p->buf && p->buf_size > 0) {
  211. probe_result = openmpt_probe_file_header_without_filesize(
  212. OPENMPT_PROBE_FILE_HEADER_FLAGS_DEFAULT,
  213. p->buf, p->buf_size,
  214. &openmpt_logfunc, NULL, NULL, NULL, NULL, NULL);
  215. if (probe_result == OPENMPT_PROBE_FILE_HEADER_RESULT_SUCCESS) {
  216. /* As probing here relies on code external to FFmpeg, do not return
  217. * AVPROBE_SCORE_MAX in order to reduce the impact in the rare
  218. * cases of false positives.
  219. */
  220. return AVPROBE_SCORE_MIME + 1;
  221. } else if (probe_result == OPENMPT_PROBE_FILE_HEADER_RESULT_WANTMOREDATA) {
  222. if (probe_openmpt_extension(p) > 0) {
  223. return AVPROBE_SCORE_RETRY;
  224. } else {
  225. if (p->buf_size >= openmpt_probe_file_header_get_recommended_size()) {
  226. /* We have already received the recommended amount of data
  227. * and still cannot decide. Return a rather low score.
  228. */
  229. return AVPROBE_SCORE_RETRY / 2;
  230. } else {
  231. /* The file extension is unknown and we have very few data
  232. * bytes available. libopenmpt cannot decide anything here,
  233. * and returning any score > 0 would result in successful
  234. * probing of random data.
  235. */
  236. return 0;
  237. }
  238. }
  239. } else if (probe_result == OPENMPT_PROBE_FILE_HEADER_RESULT_FAILURE) {
  240. return 0;
  241. }
  242. }
  243. #endif
  244. /* for older libopenmpt, fall back to file extension probing */
  245. return probe_openmpt_extension(p);
  246. }
  247. static const AVClass class_openmpt = {
  248. .class_name = "libopenmpt",
  249. .item_name = av_default_item_name,
  250. .option = options,
  251. .version = LIBAVUTIL_VERSION_INT,
  252. };
  253. AVInputFormat ff_libopenmpt_demuxer = {
  254. .name = "libopenmpt",
  255. .long_name = NULL_IF_CONFIG_SMALL("Tracker formats (libopenmpt)"),
  256. .priv_data_size = sizeof(OpenMPTContext),
  257. .read_probe = read_probe_openmpt,
  258. .read_header = read_header_openmpt,
  259. .read_packet = read_packet_openmpt,
  260. .read_close = read_close_openmpt,
  261. .read_seek = read_seek_openmpt,
  262. .priv_class = &class_openmpt,
  263. #if OPENMPT_API_VERSION_AT_LEAST(0,3,0)
  264. .extensions = "669,amf,ams,dbm,digi,dmf,dsm,dtm,far,gdm,ice,imf,it,j2b,m15,mdl,med,mmcmp,mms,mo3,mod,mptm,mt2,mtm,nst,okt,plm,ppm,psm,pt36,ptm,s3m,sfx,sfx2,st26,stk,stm,stp,ult,umx,wow,xm,xpk",
  265. #else
  266. .extensions = "669,amf,ams,dbm,digi,dmf,dsm,far,gdm,ice,imf,it,j2b,m15,mdl,med,mmcmp,mms,mo3,mod,mptm,mt2,mtm,nst,okt,plm,ppm,psm,pt36,ptm,s3m,sfx,sfx2,st26,stk,stm,ult,umx,wow,xm,xpk",
  267. #endif
  268. };