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.

88 lines
2.6KB

  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 "libavutil/attributes.h"
  19. #include "apetag.h"
  20. #include "avformat.h"
  21. #include "wv.h"
  22. typedef struct WvMuxContext {
  23. int64_t samples;
  24. } WvMuxContext;
  25. static av_cold int wv_write_header(AVFormatContext *ctx)
  26. {
  27. if (ctx->nb_streams > 1 ||
  28. ctx->streams[0]->codecpar->codec_id != AV_CODEC_ID_WAVPACK) {
  29. av_log(ctx, AV_LOG_ERROR, "This muxer only supports a single WavPack stream.\n");
  30. return AVERROR(EINVAL);
  31. }
  32. return 0;
  33. }
  34. static int wv_write_packet(AVFormatContext *ctx, AVPacket *pkt)
  35. {
  36. WvMuxContext *s = ctx->priv_data;
  37. WvHeader header;
  38. int ret;
  39. if (pkt->size < WV_HEADER_SIZE ||
  40. (ret = ff_wv_parse_header(&header, pkt->data)) < 0) {
  41. av_log(ctx, AV_LOG_ERROR, "Invalid WavPack packet.\n");
  42. return AVERROR(EINVAL);
  43. }
  44. s->samples += header.samples;
  45. avio_write(ctx->pb, pkt->data, pkt->size);
  46. return 0;
  47. }
  48. static av_cold int wv_write_trailer(AVFormatContext *ctx)
  49. {
  50. WvMuxContext *s = ctx->priv_data;
  51. /* update total number of samples in the first block */
  52. if ((ctx->pb->seekable & AVIO_SEEKABLE_NORMAL) && s->samples &&
  53. s->samples < UINT32_MAX) {
  54. int64_t pos = avio_tell(ctx->pb);
  55. avio_seek(ctx->pb, 12, SEEK_SET);
  56. avio_wl32(ctx->pb, s->samples);
  57. avio_seek(ctx->pb, pos, SEEK_SET);
  58. }
  59. ff_ape_write_tag(ctx);
  60. return 0;
  61. }
  62. AVOutputFormat ff_wv_muxer = {
  63. .name = "wv",
  64. .long_name = NULL_IF_CONFIG_SMALL("raw WavPack"),
  65. .mime_type = "audio/x-wavpack",
  66. .extensions = "wv",
  67. .priv_data_size = sizeof(WvMuxContext),
  68. .audio_codec = AV_CODEC_ID_WAVPACK,
  69. .video_codec = AV_CODEC_ID_NONE,
  70. .write_header = wv_write_header,
  71. .write_packet = wv_write_packet,
  72. .write_trailer = wv_write_trailer,
  73. .flags = AVFMT_NOTIMESTAMPS,
  74. };