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.

243 lines
8.8KB

  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 const AVClass class_openmpt = {
  194. .class_name = "libopenmpt",
  195. .item_name = av_default_item_name,
  196. .option = options,
  197. .version = LIBAVUTIL_VERSION_INT,
  198. };
  199. AVInputFormat ff_libopenmpt_demuxer = {
  200. .name = "libopenmpt",
  201. .long_name = NULL_IF_CONFIG_SMALL("Tracker formats (libopenmpt)"),
  202. .priv_data_size = sizeof(OpenMPTContext),
  203. .read_header = read_header_openmpt,
  204. .read_packet = read_packet_openmpt,
  205. .read_close = read_close_openmpt,
  206. .read_seek = read_seek_openmpt,
  207. .priv_class = &class_openmpt,
  208. #if OPENMPT_API_VERSION_AT_LEAST(0,3,0)
  209. .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",
  210. #else
  211. .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",
  212. #endif
  213. };