Browse code

lavc: add a libwavpack encoder wrapper

Anton Khirnov authored on 2013/05/26 02:22:59
Showing 8 changed files
... ...
@@ -24,6 +24,7 @@ version 10:
24 24
 - VC-1 interlaced B-frame support
25 25
 - support for WavPack muxing (raw and in Matroska)
26 26
 - Go2Webinar decoder
27
+- WavPack encoding through libwavpack
27 28
 
28 29
 
29 30
 version 9:
... ...
@@ -200,6 +200,7 @@ External library support:
200 200
   --enable-libvo-amrwbenc  enable AMR-WB encoding via libvo-amrwbenc [no]
201 201
   --enable-libvorbis       enable Vorbis encoding via libvorbis [no]
202 202
   --enable-libvpx          enable VP8 and VP9 de/encoding via libvpx [no]
203
+  --enable-libwavpack      enable wavpack encoding via libwavpack [no]
203 204
   --enable-libx264         enable H.264 encoding via x264 [no]
204 205
   --enable-libxavs         enable AVS encoding via xavs [no]
205 206
   --enable-libxvid         enable Xvid encoding via xvidcore,
... ...
@@ -1060,6 +1061,7 @@ EXTERNAL_LIBRARY_LIST="
1060 1060
     libvo_amrwbenc
1061 1061
     libvorbis
1062 1062
     libvpx
1063
+    libwavpack
1063 1064
     libx264
1064 1065
     libxavs
1065 1066
     libxvid
... ...
@@ -1790,6 +1792,7 @@ libvpx_vp8_decoder_deps="libvpx"
1790 1790
 libvpx_vp8_encoder_deps="libvpx"
1791 1791
 libvpx_vp9_decoder_deps="libvpx"
1792 1792
 libvpx_vp9_encoder_deps="libvpx"
1793
+libwavpack_encoder_deps="libwavpack"
1793 1794
 libx264_encoder_deps="libx264"
1794 1795
 libxavs_encoder_deps="libxavs"
1795 1796
 libxvid_encoder_deps="libxvid"
... ...
@@ -3735,6 +3738,7 @@ enabled libvpx     && {
3735 3735
                                 die "ERROR: libvpx encoder version must be >=0.9.6"; }
3736 3736
     enabled libvpx_vp9_decoder && { check_lib2 "vpx/vpx_decoder.h vpx/vp8dx.h" "vpx_codec_vp9_dx" -lvpx || disable libvpx_vp9_decoder;  }
3737 3737
     enabled libvpx_vp9_encoder && { check_lib2 "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_vp9_cx" -lvpx || disable libvpx_vp9_encoder; } }
3738
+enabled libwavpack && require libwavpack wavpack/wavpack.h WavpackOpenFileOutput  -lwavpack
3738 3739
 enabled libx264    && require  libx264 x264.h x264_encoder_encode -lx264 &&
3739 3740
                       { check_cpp_condition x264.h "X264_BUILD >= 118" ||
3740 3741
                         die "ERROR: libx264 version must be >= 0.118."; }
... ...
@@ -412,6 +412,35 @@ Selected by Encoder (default)
412 412
 
413 413
 @end table
414 414
 
415
+@section libwavpack
416
+
417
+A wrapper providing WavPack encoding through libwavpack.
418
+
419
+Only lossless mode using 32-bit integer samples is supported currently.
420
+The @option{compression_level} option can be used to control speed vs.
421
+compression tradeoff, with the values mapped to libwavpack as follows:
422
+
423
+@table @option
424
+
425
+@item 0
426
+Fast mode - corresponding to the wavpack @option{-f} option.
427
+
428
+@item 1
429
+Normal (default) settings.
430
+
431
+@item 2
432
+High quality - corresponding to the wavpack @option{-h} option.
433
+
434
+@item 3
435
+Very high quality - corresponding to the wavpack @option{-hh} option.
436
+
437
+@item 4-8
438
+Same as 3, but with extra processing enabled - corresponding to the wavpack
439
+@option{-x} option. I.e. 4 is the same as @option{-x2} and 8 is the same as
440
+@option{-x6}.
441
+
442
+@end table
443
+
415 444
 @c man end AUDIO ENCODERS
416 445
 
417 446
 @chapter Video Encoders
... ...
@@ -79,6 +79,14 @@ Go to @url{http://www.webmproject.org/} and follow the instructions for
79 79
 installing the library. Then pass @code{--enable-libvpx} to configure to
80 80
 enable it.
81 81
 
82
+@section libwavpack
83
+
84
+Libav can make use of the libwavpack library for WavPack encoding.
85
+
86
+Go to @url{http://www.wavpack.com/} and follow the instructions for
87
+installing the library. Then pass @code{--enable-libwavpack} to configure to
88
+enable it.
89
+
82 90
 @section x264
83 91
 
84 92
 Libav can make use of the x264 library for H.264 encoding.
... ...
@@ -810,7 +818,8 @@ following image formats are supported:
810 810
 @item TwinVQ (VQF flavor)    @tab     @tab  X
811 811
 @item Vorbis                 @tab  E  @tab  X
812 812
     @tab A native but very primitive encoder exists.
813
-@item WavPack                @tab     @tab  X
813
+@item WavPack                @tab  E  @tab  X
814
+    @tab supported through external library libwavpack
814 815
 @item Westwood Audio (SND1)  @tab     @tab  X
815 816
 @item Windows Media Audio 1  @tab  X  @tab  X
816 817
 @item Windows Media Audio 2  @tab  X  @tab  X
... ...
@@ -599,6 +599,7 @@ OBJS-$(CONFIG_LIBVPX_VP8_DECODER)         += libvpxdec.o
599 599
 OBJS-$(CONFIG_LIBVPX_VP8_ENCODER)         += libvpxenc.o
600 600
 OBJS-$(CONFIG_LIBVPX_VP9_DECODER)         += libvpxdec.o
601 601
 OBJS-$(CONFIG_LIBVPX_VP9_ENCODER)         += libvpxenc.o
602
+OBJS-$(CONFIG_LIBWAVPACK_ENCODER)         += libwavpackenc.o
602 603
 OBJS-$(CONFIG_LIBX264_ENCODER)            += libx264.o
603 604
 OBJS-$(CONFIG_LIBXAVS_ENCODER)            += libxavs.o
604 605
 OBJS-$(CONFIG_LIBXVID_ENCODER)            += libxvid.o
... ...
@@ -432,6 +432,7 @@ void avcodec_register_all(void)
432 432
     REGISTER_ENCODER(LIBVORBIS,         libvorbis);
433 433
     REGISTER_ENCDEC (LIBVPX_VP8,        libvpx_vp8);
434 434
     REGISTER_ENCDEC (LIBVPX_VP9,        libvpx_vp9);
435
+    REGISTER_ENCODER(LIBWAVPACK,        libwavpack);
435 436
     REGISTER_ENCODER(LIBX264,           libx264);
436 437
     REGISTER_ENCODER(LIBXAVS,           libxavs);
437 438
     REGISTER_ENCODER(LIBXVID,           libxvid);
438 439
new file mode 100644
... ...
@@ -0,0 +1,194 @@
0
+/*
1
+ * This file is part of Libav.
2
+ *
3
+ * Libav is free software; you can redistribute it and/or
4
+ * modify it under the terms of the GNU Lesser General Public
5
+ * License as published by the Free Software Foundation; either
6
+ * version 2.1 of the License, or (at your option) any later version.
7
+ *
8
+ * Libav is distributed in the hope that it will be useful,
9
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
+ * Lesser General Public License for more details.
12
+ *
13
+ * You should have received a copy of the GNU Lesser General Public
14
+ * License along with Libav; if not, write to the Free Software
15
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+ */
17
+
18
+#include <wavpack/wavpack.h>
19
+#include <string.h>
20
+
21
+#include "libavutil/attributes.h"
22
+#include "libavutil/opt.h"
23
+#include "libavutil/samplefmt.h"
24
+
25
+#include "audio_frame_queue.h"
26
+#include "avcodec.h"
27
+#include "internal.h"
28
+
29
+#define WV_DEFAULT_BLOCK_SIZE 32768
30
+
31
+typedef struct LibWavpackContext {
32
+    const AVClass *class;
33
+    WavpackContext *wv;
34
+    AudioFrameQueue afq;
35
+
36
+    AVPacket *pkt;
37
+    int user_size;
38
+
39
+    int got_output;
40
+} LibWavpackContext;
41
+
42
+static int wavpack_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
43
+                                const AVFrame *frame, int *got_output)
44
+{
45
+    LibWavpackContext *s = avctx->priv_data;
46
+    int ret;
47
+
48
+    s->got_output = 0;
49
+    s->pkt        = pkt;
50
+    s->user_size  = pkt->size;
51
+
52
+    if (frame) {
53
+        ret = ff_af_queue_add(&s->afq, frame);
54
+        if (ret < 0)
55
+            return ret;
56
+
57
+        ret = WavpackPackSamples(s->wv, (int32_t*)frame->data[0], frame->nb_samples);
58
+        if (!ret) {
59
+            av_log(avctx, AV_LOG_ERROR, "Error encoding a frame: %s\n",
60
+                   WavpackGetErrorMessage(s->wv));
61
+            return AVERROR_UNKNOWN;
62
+        }
63
+    }
64
+
65
+    if (!s->got_output &&
66
+        (!frame || frame->nb_samples < avctx->frame_size)) {
67
+        ret = WavpackFlushSamples(s->wv);
68
+        if (!ret) {
69
+            av_log(avctx, AV_LOG_ERROR, "Error flushing the encoder: %s\n",
70
+                   WavpackGetErrorMessage(s->wv));
71
+            return AVERROR_UNKNOWN;
72
+        }
73
+    }
74
+
75
+    if (s->got_output) {
76
+        ff_af_queue_remove(&s->afq, avctx->frame_size, &pkt->pts, &pkt->duration);
77
+        *got_output = 1;
78
+    }
79
+
80
+    return 0;
81
+}
82
+
83
+static int encode_callback(void *id, void *data, int32_t count)
84
+{
85
+    AVCodecContext *avctx = id;
86
+    LibWavpackContext *s  = avctx->priv_data;
87
+    int ret, offset = s->pkt->size;
88
+
89
+    if (s->user_size) {
90
+        if (s->user_size - count < s->pkt->size) {
91
+            av_log(avctx, AV_LOG_ERROR, "Provided packet too small.\n");
92
+            return 0;
93
+        }
94
+        s->pkt->size += count;
95
+    } else {
96
+        ret = av_grow_packet(s->pkt, count);
97
+        if (ret < 0) {
98
+            av_log(avctx, AV_LOG_ERROR, "Error allocating output packet.\n");
99
+            return 0;
100
+        }
101
+    }
102
+
103
+    memcpy(s->pkt->data + offset, data, count);
104
+
105
+    s->got_output = 1;
106
+
107
+    return 1;
108
+}
109
+
110
+static av_cold int wavpack_encode_init(AVCodecContext *avctx)
111
+{
112
+    LibWavpackContext *s = avctx->priv_data;
113
+    WavpackConfig config = { 0 };
114
+    int ret;
115
+
116
+    s->wv = WavpackOpenFileOutput(encode_callback, avctx, NULL);
117
+    if (!s->wv) {
118
+        av_log(avctx, AV_LOG_ERROR, "Error allocating the encoder.\n");
119
+        return AVERROR(ENOMEM);
120
+    }
121
+
122
+    if (!avctx->frame_size)
123
+        avctx->frame_size = WV_DEFAULT_BLOCK_SIZE;
124
+
125
+    config.bytes_per_sample = 4;
126
+    config.bits_per_sample  = 32;
127
+    config.block_samples    = avctx->frame_size;
128
+    config.channel_mask     = avctx->channel_layout;
129
+    config.num_channels     = avctx->channels;
130
+    config.sample_rate      = avctx->sample_rate;
131
+
132
+    if (avctx->compression_level != FF_COMPRESSION_DEFAULT) {
133
+        if (avctx->compression_level >= 3) {
134
+            config.flags |= CONFIG_VERY_HIGH_FLAG;
135
+
136
+            if      (avctx->compression_level >= 8)
137
+                config.xmode = 6;
138
+            else if (avctx->compression_level >= 7)
139
+                config.xmode = 5;
140
+            else if (avctx->compression_level >= 6)
141
+                config.xmode = 4;
142
+            else if (avctx->compression_level >= 5)
143
+                config.xmode = 3;
144
+            else if (avctx->compression_level >= 4)
145
+                config.xmode = 2;
146
+        } else if (avctx->compression_level >= 2)
147
+            config.flags |= CONFIG_HIGH_FLAG;
148
+        else if (avctx->compression_level < 1)
149
+            config.flags |= CONFIG_FAST_FLAG;
150
+    }
151
+
152
+    ret = WavpackSetConfiguration(s->wv, &config, -1);
153
+    if (!ret)
154
+        goto fail;
155
+
156
+    ret = WavpackPackInit(s->wv);
157
+    if (!ret)
158
+        goto fail;
159
+
160
+    ff_af_queue_init(avctx, &s->afq);
161
+
162
+    return 0;
163
+
164
+fail:
165
+    av_log(avctx, AV_LOG_ERROR, "Error configuring the encoder: %s.\n",
166
+           WavpackGetErrorMessage(s->wv));
167
+    WavpackCloseFile(s->wv);
168
+    return AVERROR_UNKNOWN;
169
+}
170
+
171
+static av_cold int wavpack_encode_close(AVCodecContext *avctx)
172
+{
173
+    LibWavpackContext *s = avctx->priv_data;
174
+
175
+    WavpackCloseFile(s->wv);
176
+
177
+    ff_af_queue_close(&s->afq);
178
+
179
+    return 0;
180
+}
181
+
182
+AVCodec ff_libwavpack_encoder = {
183
+    .name           = "libwavpack",
184
+    .type           = AVMEDIA_TYPE_AUDIO,
185
+    .id             = AV_CODEC_ID_WAVPACK,
186
+    .priv_data_size = sizeof(LibWavpackContext),
187
+    .init           = wavpack_encode_init,
188
+    .encode2        = wavpack_encode_frame,
189
+    .close          = wavpack_encode_close,
190
+    .capabilities   = CODEC_CAP_DELAY | CODEC_CAP_SMALL_LAST_FRAME,
191
+    .sample_fmts    = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32,
192
+                                                     AV_SAMPLE_FMT_NONE },
193
+};
... ...
@@ -27,7 +27,7 @@
27 27
  */
28 28
 
29 29
 #define LIBAVCODEC_VERSION_MAJOR 55
30
-#define LIBAVCODEC_VERSION_MINOR  8
30
+#define LIBAVCODEC_VERSION_MINOR  9
31 31
 #define LIBAVCODEC_VERSION_MICRO  0
32 32
 
33 33
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \