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.

195 lines
5.5KB

  1. /*
  2. * This file is part of Libav.
  3. *
  4. * Libav is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * Libav is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with Libav; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include <wavpack/wavpack.h>
  19. #include <string.h>
  20. #include "libavutil/attributes.h"
  21. #include "libavutil/opt.h"
  22. #include "libavutil/samplefmt.h"
  23. #include "audio_frame_queue.h"
  24. #include "avcodec.h"
  25. #include "internal.h"
  26. #define WV_DEFAULT_BLOCK_SIZE 32768
  27. typedef struct LibWavpackContext {
  28. const AVClass *class;
  29. WavpackContext *wv;
  30. AudioFrameQueue afq;
  31. AVPacket *pkt;
  32. int user_size;
  33. int got_output;
  34. } LibWavpackContext;
  35. static int wavpack_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
  36. const AVFrame *frame, int *got_output)
  37. {
  38. LibWavpackContext *s = avctx->priv_data;
  39. int ret;
  40. s->got_output = 0;
  41. s->pkt = pkt;
  42. s->user_size = pkt->size;
  43. if (frame) {
  44. ret = ff_af_queue_add(&s->afq, frame);
  45. if (ret < 0)
  46. return ret;
  47. ret = WavpackPackSamples(s->wv, (int32_t*)frame->data[0], frame->nb_samples);
  48. if (!ret) {
  49. av_log(avctx, AV_LOG_ERROR, "Error encoding a frame: %s\n",
  50. WavpackGetErrorMessage(s->wv));
  51. return AVERROR_UNKNOWN;
  52. }
  53. }
  54. if (!s->got_output &&
  55. (!frame || frame->nb_samples < avctx->frame_size)) {
  56. ret = WavpackFlushSamples(s->wv);
  57. if (!ret) {
  58. av_log(avctx, AV_LOG_ERROR, "Error flushing the encoder: %s\n",
  59. WavpackGetErrorMessage(s->wv));
  60. return AVERROR_UNKNOWN;
  61. }
  62. }
  63. if (s->got_output) {
  64. ff_af_queue_remove(&s->afq, avctx->frame_size, &pkt->pts, &pkt->duration);
  65. *got_output = 1;
  66. }
  67. return 0;
  68. }
  69. static int encode_callback(void *id, void *data, int32_t count)
  70. {
  71. AVCodecContext *avctx = id;
  72. LibWavpackContext *s = avctx->priv_data;
  73. int ret, offset = s->pkt->size;
  74. if (s->user_size) {
  75. if (s->user_size - count < s->pkt->size) {
  76. av_log(avctx, AV_LOG_ERROR, "Provided packet too small.\n");
  77. return 0;
  78. }
  79. s->pkt->size += count;
  80. } else {
  81. ret = av_grow_packet(s->pkt, count);
  82. if (ret < 0) {
  83. av_log(avctx, AV_LOG_ERROR, "Error allocating output packet.\n");
  84. return 0;
  85. }
  86. }
  87. memcpy(s->pkt->data + offset, data, count);
  88. s->got_output = 1;
  89. return 1;
  90. }
  91. static av_cold int wavpack_encode_init(AVCodecContext *avctx)
  92. {
  93. LibWavpackContext *s = avctx->priv_data;
  94. WavpackConfig config = { 0 };
  95. int ret;
  96. s->wv = WavpackOpenFileOutput(encode_callback, avctx, NULL);
  97. if (!s->wv) {
  98. av_log(avctx, AV_LOG_ERROR, "Error allocating the encoder.\n");
  99. return AVERROR(ENOMEM);
  100. }
  101. if (!avctx->frame_size)
  102. avctx->frame_size = WV_DEFAULT_BLOCK_SIZE;
  103. config.bytes_per_sample = 4;
  104. config.bits_per_sample = 32;
  105. config.block_samples = avctx->frame_size;
  106. config.channel_mask = avctx->channel_layout;
  107. config.num_channels = avctx->channels;
  108. config.sample_rate = avctx->sample_rate;
  109. if (avctx->compression_level != FF_COMPRESSION_DEFAULT) {
  110. if (avctx->compression_level >= 3) {
  111. config.flags |= CONFIG_VERY_HIGH_FLAG;
  112. if (avctx->compression_level >= 8)
  113. config.xmode = 6;
  114. else if (avctx->compression_level >= 7)
  115. config.xmode = 5;
  116. else if (avctx->compression_level >= 6)
  117. config.xmode = 4;
  118. else if (avctx->compression_level >= 5)
  119. config.xmode = 3;
  120. else if (avctx->compression_level >= 4)
  121. config.xmode = 2;
  122. } else if (avctx->compression_level >= 2)
  123. config.flags |= CONFIG_HIGH_FLAG;
  124. else if (avctx->compression_level < 1)
  125. config.flags |= CONFIG_FAST_FLAG;
  126. }
  127. ret = WavpackSetConfiguration(s->wv, &config, -1);
  128. if (!ret)
  129. goto fail;
  130. ret = WavpackPackInit(s->wv);
  131. if (!ret)
  132. goto fail;
  133. ff_af_queue_init(avctx, &s->afq);
  134. return 0;
  135. fail:
  136. av_log(avctx, AV_LOG_ERROR, "Error configuring the encoder: %s.\n",
  137. WavpackGetErrorMessage(s->wv));
  138. WavpackCloseFile(s->wv);
  139. return AVERROR_UNKNOWN;
  140. }
  141. static av_cold int wavpack_encode_close(AVCodecContext *avctx)
  142. {
  143. LibWavpackContext *s = avctx->priv_data;
  144. WavpackCloseFile(s->wv);
  145. ff_af_queue_close(&s->afq);
  146. return 0;
  147. }
  148. AVCodec ff_libwavpack_encoder = {
  149. .name = "libwavpack",
  150. .type = AVMEDIA_TYPE_AUDIO,
  151. .id = AV_CODEC_ID_WAVPACK,
  152. .priv_data_size = sizeof(LibWavpackContext),
  153. .init = wavpack_encode_init,
  154. .encode2 = wavpack_encode_frame,
  155. .close = wavpack_encode_close,
  156. .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME,
  157. .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32,
  158. AV_SAMPLE_FMT_NONE },
  159. };