libavformat/wvenc.c
a3a0774b
 /*
  * WavPack muxer
a4037066
  * Copyright (c) 2013 Konstantin Shishkov <kostya.shishkov@gmail.com>
a3a0774b
  * Copyright (c) 2012 Paul B Mahol
  *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
  * FFmpeg is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
2d2d6a48
 #include "libavutil/attributes.h"
 
c25dc1f9
 #include "apetag.h"
2d2d6a48
 #include "avformat.h"
 #include "wv.h"
a3a0774b
 
2d2d6a48
 typedef struct WvMuxContext {
269fc8e0
     int64_t samples;
2d2d6a48
 } WvMuxContext;
a3a0774b
 
2d2d6a48
 static av_cold int wv_write_header(AVFormatContext *ctx)
a3a0774b
 {
2d2d6a48
     if (ctx->nb_streams > 1 ||
9200514a
         ctx->streams[0]->codecpar->codec_id != AV_CODEC_ID_WAVPACK) {
2d2d6a48
         av_log(ctx, AV_LOG_ERROR, "This muxer only supports a single WavPack stream.\n");
a3a0774b
         return AVERROR(EINVAL);
     }
2d2d6a48
 
a3a0774b
     return 0;
 }
 
2d2d6a48
 static int wv_write_packet(AVFormatContext *ctx, AVPacket *pkt)
a3a0774b
 {
2d2d6a48
     WvMuxContext *s = ctx->priv_data;
     WvHeader header;
     int ret;
 
     if (pkt->size < WV_HEADER_SIZE ||
         (ret = ff_wv_parse_header(&header, pkt->data)) < 0) {
         av_log(ctx, AV_LOG_ERROR, "Invalid WavPack packet.\n");
         return AVERROR(EINVAL);
     }
     s->samples += header.samples;
a3a0774b
 
269fc8e0
     avio_write(ctx->pb, pkt->data, pkt->size);
a3a0774b
 
     return 0;
 }
 
2d2d6a48
 static av_cold int wv_write_trailer(AVFormatContext *ctx)
a3a0774b
 {
2d2d6a48
     WvMuxContext *s = ctx->priv_data;
c25dc1f9
 
2d2d6a48
     /* update total number of samples in the first block */
83548fe8
     if ((ctx->pb->seekable & AVIO_SEEKABLE_NORMAL) && s->samples &&
2d2d6a48
         s->samples < UINT32_MAX) {
         int64_t pos = avio_tell(ctx->pb);
269fc8e0
         avio_seek(ctx->pb, 12, SEEK_SET);
2d2d6a48
         avio_wl32(ctx->pb, s->samples);
         avio_seek(ctx->pb, pos, SEEK_SET);
a3a0774b
     }
 
2d2d6a48
     ff_ape_write_tag(ctx);
a3a0774b
     return 0;
 }
 
 AVOutputFormat ff_wv_muxer = {
     .name              = "wv",
2d2d6a48
     .long_name         = NULL_IF_CONFIG_SMALL("raw WavPack"),
     .mime_type         = "audio/x-wavpack",
a3a0774b
     .extensions        = "wv",
2d2d6a48
     .priv_data_size    = sizeof(WvMuxContext),
7a72695c
     .audio_codec       = AV_CODEC_ID_WAVPACK,
     .video_codec       = AV_CODEC_ID_NONE,
2d2d6a48
     .write_header      = wv_write_header,
     .write_packet      = wv_write_packet,
     .write_trailer     = wv_write_trailer,
269fc8e0
     .flags             = AVFMT_NOTIMESTAMPS,
a3a0774b
 };