FFmpeg  4.0
libwavpackenc.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg 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  * FFmpeg 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 FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <wavpack/wavpack.h>
20 #include <string.h>
21 
22 #include "libavutil/attributes.h"
23 #include "libavutil/opt.h"
24 #include "libavutil/samplefmt.h"
25 
26 #include "audio_frame_queue.h"
27 #include "avcodec.h"
28 #include "internal.h"
29 
30 #define WV_DEFAULT_BLOCK_SIZE 32768
31 
32 typedef struct LibWavpackContext {
33  const AVClass *class;
36 
38  int user_size;
39 
42 
44  const AVFrame *frame, int *got_output)
45 {
46  LibWavpackContext *s = avctx->priv_data;
47  int ret;
48 
49  s->got_output = 0;
50  s->pkt = pkt;
51  s->user_size = pkt->size;
52 
53  if (frame) {
54  ret = ff_af_queue_add(&s->afq, frame);
55  if (ret < 0)
56  return ret;
57 
58  ret = WavpackPackSamples(s->wv, (int32_t*)frame->data[0], frame->nb_samples);
59  if (!ret) {
60  av_log(avctx, AV_LOG_ERROR, "Error encoding a frame: %s\n",
61  WavpackGetErrorMessage(s->wv));
62  return AVERROR_UNKNOWN;
63  }
64  }
65 
66  if (!s->got_output &&
67  (!frame || frame->nb_samples < avctx->frame_size)) {
68  ret = WavpackFlushSamples(s->wv);
69  if (!ret) {
70  av_log(avctx, AV_LOG_ERROR, "Error flushing the encoder: %s\n",
71  WavpackGetErrorMessage(s->wv));
72  return AVERROR_UNKNOWN;
73  }
74  }
75 
76  if (s->got_output) {
77  ff_af_queue_remove(&s->afq, avctx->frame_size, &pkt->pts, &pkt->duration);
78  *got_output = 1;
79  }
80 
81  return 0;
82 }
83 
84 static int encode_callback(void *id, void *data, int32_t count)
85 {
86  AVCodecContext *avctx = id;
87  LibWavpackContext *s = avctx->priv_data;
88  int ret, offset = s->pkt->size;
89 
90  if (s->user_size) {
91  if (s->user_size - count < s->pkt->size) {
92  av_log(avctx, AV_LOG_ERROR, "Provided packet too small.\n");
93  return 0;
94  }
95  s->pkt->size += count;
96  } else {
97  ret = av_grow_packet(s->pkt, count);
98  if (ret < 0) {
99  av_log(avctx, AV_LOG_ERROR, "Error allocating output packet.\n");
100  return 0;
101  }
102  }
103 
104  memcpy(s->pkt->data + offset, data, count);
105 
106  s->got_output = 1;
107 
108  return 1;
109 }
110 
112 {
113  LibWavpackContext *s = avctx->priv_data;
114  WavpackConfig config = { 0 };
115  int ret;
116 
117  s->wv = WavpackOpenFileOutput(encode_callback, avctx, NULL);
118  if (!s->wv) {
119  av_log(avctx, AV_LOG_ERROR, "Error allocating the encoder.\n");
120  return AVERROR(ENOMEM);
121  }
122 
123  if (!avctx->frame_size)
125 
126  config.bytes_per_sample = 4;
127  config.bits_per_sample = 32;
128  config.block_samples = avctx->frame_size;
129  config.channel_mask = avctx->channel_layout;
130  config.num_channels = avctx->channels;
131  config.sample_rate = avctx->sample_rate;
132 
134  if (avctx->compression_level >= 3) {
135  config.flags |= CONFIG_VERY_HIGH_FLAG;
136 
137  if (avctx->compression_level >= 8)
138  config.xmode = 6;
139  else if (avctx->compression_level >= 7)
140  config.xmode = 5;
141  else if (avctx->compression_level >= 6)
142  config.xmode = 4;
143  else if (avctx->compression_level >= 5)
144  config.xmode = 3;
145  else if (avctx->compression_level >= 4)
146  config.xmode = 2;
147  } else if (avctx->compression_level >= 2)
148  config.flags |= CONFIG_HIGH_FLAG;
149  else if (avctx->compression_level < 1)
150  config.flags |= CONFIG_FAST_FLAG;
151  }
152 
153  ret = WavpackSetConfiguration(s->wv, &config, -1);
154  if (!ret)
155  goto fail;
156 
157  ret = WavpackPackInit(s->wv);
158  if (!ret)
159  goto fail;
160 
161  ff_af_queue_init(avctx, &s->afq);
162 
163  return 0;
164 
165 fail:
166  av_log(avctx, AV_LOG_ERROR, "Error configuring the encoder: %s.\n",
167  WavpackGetErrorMessage(s->wv));
168  WavpackCloseFile(s->wv);
169  return AVERROR_UNKNOWN;
170 }
171 
173 {
174  LibWavpackContext *s = avctx->priv_data;
175 
176  WavpackCloseFile(s->wv);
177 
178  ff_af_queue_close(&s->afq);
179 
180  return 0;
181 }
182 
184  .name = "libwavpack",
185  .type = AVMEDIA_TYPE_AUDIO,
186  .id = AV_CODEC_ID_WAVPACK,
187  .priv_data_size = sizeof(LibWavpackContext),
189  .encode2 = wavpack_encode_frame,
190  .close = wavpack_encode_close,
192  .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32,
194  .wrapper_name = "libwavpack",
195 };
void ff_af_queue_remove(AudioFrameQueue *afq, int nb_samples, int64_t *pts, int64_t *duration)
Remove frame(s) from the queue.
#define NULL
Definition: coverity.c:32
const char * s
Definition: avisynth_c.h:768
#define FF_COMPRESSION_DEFAULT
Definition: avcodec.h:1591
This structure describes decoded (raw) audio or video data.
Definition: frame.h:218
static av_cold int wavpack_encode_init(AVCodecContext *avctx)
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int size
Definition: avcodec.h:1431
AVCodec.
Definition: avcodec.h:3408
Macro definitions for various function/variable attributes.
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
Definition: avcodec.h:984
#define av_cold
Definition: attributes.h:82
AVOptions.
av_cold void ff_af_queue_init(AVCodecContext *avctx, AudioFrameQueue *afq)
Initialize AudioFrameQueue.
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: avcodec.h:1448
WavpackContext * wv
Definition: libwavpackenc.c:34
static AVFrame * frame
const char data[16]
Definition: mxf.c:90
uint8_t * data
Definition: avcodec.h:1430
signed 32 bits
Definition: samplefmt.h:62
#define av_log(a,...)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
#define AVERROR(e)
Definition: error.h:43
static int wavpack_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_output)
Definition: libwavpackenc.c:43
static av_cold int wavpack_encode_close(AVCodecContext *avctx)
const char * name
Name of the codec implementation.
Definition: avcodec.h:3415
static const uint8_t offset[127][2]
Definition: vf_spp.c:92
int ff_af_queue_add(AudioFrameQueue *afq, const AVFrame *f)
Add a frame to the queue.
#define fail()
Definition: checkasm.h:116
uint64_t channel_layout
Audio channel layout.
Definition: avcodec.h:2224
#define AV_CODEC_CAP_SMALL_LAST_FRAME
Codec can be fed a final frame with a smaller size.
Definition: avcodec.h:989
AudioFrameQueue afq
Definition: libwavpackenc.c:35
int32_t
#define WV_DEFAULT_BLOCK_SIZE
Definition: libwavpackenc.c:30
int frame_size
Number of samples per channel in an audio frame.
Definition: avcodec.h:2193
Libavcodec external API header.
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
int compression_level
Definition: avcodec.h:1590
int sample_rate
samples per second
Definition: avcodec.h:2173
main external API structure.
Definition: avcodec.h:1518
Describe the class of an AVClass context structure.
Definition: log.h:67
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:232
static int encode_callback(void *id, void *data, int32_t count)
Definition: libwavpackenc.c:84
common internal api header.
int av_grow_packet(AVPacket *pkt, int grow_by)
Increase packet size, correctly zeroing padding.
Definition: avpacket.c:109
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
void * priv_data
Definition: avcodec.h:1545
AVCodec ff_libwavpack_encoder
int channels
number of audio channels
Definition: avcodec.h:2174
void ff_af_queue_close(AudioFrameQueue *afq)
Close AudioFrameQueue.
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:701
void INT64 INT64 count
Definition: avisynth_c.h:690
enum AVCodecID id
This structure stores compressed data.
Definition: avcodec.h:1407
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:284
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1423