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.

202 lines
6.1KB

  1. /*
  2. * 8SVX audio decoder
  3. * Copyright (C) 2008 Jaikrishnan Menon
  4. *
  5. * This file is part of Libav.
  6. *
  7. * Libav 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. * Libav 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 Libav; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. /**
  22. * @file
  23. * 8svx audio decoder
  24. * @author Jaikrishnan Menon
  25. *
  26. * supports: fibonacci delta encoding
  27. * : exponential encoding
  28. */
  29. #include "avcodec.h"
  30. /** decoder context */
  31. typedef struct EightSvxContext {
  32. uint8_t fib_acc[2];
  33. const int8_t *table;
  34. /* buffer used to store the whole first packet.
  35. data is only sent as one large packet */
  36. uint8_t *data[2];
  37. int data_size;
  38. int data_idx;
  39. } EightSvxContext;
  40. static const int8_t fibonacci[16] = { -34, -21, -13, -8, -5, -3, -2, -1,
  41. 0, 1, 2, 3, 5, 8, 13, 21 };
  42. static const int8_t exponential[16] = { -128, -64, -32, -16, -8, -4, -2, -1,
  43. 0, 1, 2, 4, 8, 16, 32, 64 };
  44. #define MAX_FRAME_SIZE 32768
  45. /**
  46. * Delta decode the compressed values in src, and put the resulting
  47. * decoded samples in dst.
  48. *
  49. * @param[in,out] state starting value. it is saved for use in the next call.
  50. */
  51. static void delta_decode(uint8_t *dst, const uint8_t *src, int src_size,
  52. uint8_t *state, const int8_t *table, int channels)
  53. {
  54. uint8_t val = *state;
  55. while (src_size--) {
  56. uint8_t d = *src++;
  57. val = av_clip_uint8(val + table[d & 0xF]);
  58. *dst = val;
  59. dst += channels;
  60. val = av_clip_uint8(val + table[d >> 4]);
  61. *dst = val;
  62. dst += channels;
  63. }
  64. *state = val;
  65. }
  66. /** decode a frame */
  67. static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
  68. AVPacket *avpkt)
  69. {
  70. EightSvxContext *esc = avctx->priv_data;
  71. int buf_size;
  72. uint8_t *out_data = data;
  73. int out_data_size;
  74. /* for the first packet, copy data to buffer */
  75. if (avpkt->data) {
  76. int chan_size = (avpkt->size / avctx->channels) - 2;
  77. if (avpkt->size < 2) {
  78. av_log(avctx, AV_LOG_ERROR, "packet size is too small\n");
  79. return AVERROR(EINVAL);
  80. }
  81. if (esc->data[0]) {
  82. av_log(avctx, AV_LOG_ERROR, "unexpected data after first packet\n");
  83. return AVERROR(EINVAL);
  84. }
  85. esc->fib_acc[0] = avpkt->data[1] + 128;
  86. if (avctx->channels == 2)
  87. esc->fib_acc[1] = avpkt->data[2+chan_size+1] + 128;
  88. esc->data_idx = 0;
  89. esc->data_size = chan_size;
  90. if (!(esc->data[0] = av_malloc(chan_size)))
  91. return AVERROR(ENOMEM);
  92. if (avctx->channels == 2) {
  93. if (!(esc->data[1] = av_malloc(chan_size))) {
  94. av_freep(&esc->data[0]);
  95. return AVERROR(ENOMEM);
  96. }
  97. }
  98. memcpy(esc->data[0], &avpkt->data[2], chan_size);
  99. if (avctx->channels == 2)
  100. memcpy(esc->data[1], &avpkt->data[2+chan_size+2], chan_size);
  101. }
  102. if (!esc->data[0]) {
  103. av_log(avctx, AV_LOG_ERROR, "unexpected empty packet\n");
  104. return AVERROR(EINVAL);
  105. }
  106. /* decode next piece of data from the buffer */
  107. buf_size = FFMIN(MAX_FRAME_SIZE, esc->data_size - esc->data_idx);
  108. if (buf_size <= 0) {
  109. *data_size = 0;
  110. return avpkt->size;
  111. }
  112. out_data_size = buf_size * 2 * avctx->channels;
  113. if (*data_size < out_data_size) {
  114. av_log(avctx, AV_LOG_ERROR, "Provided buffer with size %d is too small.\n",
  115. *data_size);
  116. return AVERROR(EINVAL);
  117. }
  118. delta_decode(out_data, &esc->data[0][esc->data_idx], buf_size,
  119. &esc->fib_acc[0], esc->table, avctx->channels);
  120. if (avctx->channels == 2) {
  121. delta_decode(&out_data[1], &esc->data[1][esc->data_idx], buf_size,
  122. &esc->fib_acc[1], esc->table, avctx->channels);
  123. }
  124. esc->data_idx += buf_size;
  125. *data_size = out_data_size;
  126. return avpkt->size;
  127. }
  128. /** initialize 8svx decoder */
  129. static av_cold int eightsvx_decode_init(AVCodecContext *avctx)
  130. {
  131. EightSvxContext *esc = avctx->priv_data;
  132. if (avctx->channels < 1 || avctx->channels > 2) {
  133. av_log(avctx, AV_LOG_ERROR, "8SVX does not support more than 2 channels\n");
  134. return AVERROR(EINVAL);
  135. }
  136. switch(avctx->codec->id) {
  137. case CODEC_ID_8SVX_FIB:
  138. esc->table = fibonacci;
  139. break;
  140. case CODEC_ID_8SVX_EXP:
  141. esc->table = exponential;
  142. break;
  143. default:
  144. return -1;
  145. }
  146. avctx->sample_fmt = AV_SAMPLE_FMT_U8;
  147. return 0;
  148. }
  149. static av_cold int eightsvx_decode_close(AVCodecContext *avctx)
  150. {
  151. EightSvxContext *esc = avctx->priv_data;
  152. av_freep(&esc->data[0]);
  153. av_freep(&esc->data[1]);
  154. return 0;
  155. }
  156. AVCodec ff_eightsvx_fib_decoder = {
  157. .name = "8svx_fib",
  158. .type = AVMEDIA_TYPE_AUDIO,
  159. .id = CODEC_ID_8SVX_FIB,
  160. .priv_data_size = sizeof (EightSvxContext),
  161. .init = eightsvx_decode_init,
  162. .close = eightsvx_decode_close,
  163. .decode = eightsvx_decode_frame,
  164. .capabilities = CODEC_CAP_DELAY,
  165. .long_name = NULL_IF_CONFIG_SMALL("8SVX fibonacci"),
  166. };
  167. AVCodec ff_eightsvx_exp_decoder = {
  168. .name = "8svx_exp",
  169. .type = AVMEDIA_TYPE_AUDIO,
  170. .id = CODEC_ID_8SVX_EXP,
  171. .priv_data_size = sizeof (EightSvxContext),
  172. .init = eightsvx_decode_init,
  173. .close = eightsvx_decode_close,
  174. .decode = eightsvx_decode_frame,
  175. .capabilities = CODEC_CAP_DELAY,
  176. .long_name = NULL_IF_CONFIG_SMALL("8SVX exponential"),
  177. };