Browse code

libshine fixed point MP3 encoding support

Signed-off-by: Paul B Mahol <onemda@gmail.com>

Paul B Mahol authored on 2012/07/30 03:20:00
Showing 4 changed files
... ...
@@ -218,6 +218,7 @@ External library support:
218 218
   --enable-libquvi         enable quvi input via libquvi [no]
219 219
   --enable-librtmp         enable RTMP[E] support via librtmp [no]
220 220
   --enable-libschroedinger enable Dirac de/encoding via libschroedinger [no]
221
+  --enable-libshine        enable fixed-point MP3 encoding via libshine [no]
221 222
   --enable-libsoxr         enable Include libsoxr resampling [no]
222 223
   --enable-libspeex        enable Speex de/encoding via libspeex [no]
223 224
   --enable-libstagefright-h264  enable H.264 decoding via libstagefright [no]
... ...
@@ -1172,6 +1173,7 @@ EXTERNAL_LIBRARY_LIST="
1172 1172
     libquvi
1173 1173
     librtmp
1174 1174
     libschroedinger
1175
+    libshine
1175 1176
     libsoxr
1176 1177
     libspeex
1177 1178
     libstagefright_h264
... ...
@@ -1976,6 +1978,8 @@ libopus_encoder_select="audio_frame_queue"
1976 1976
 libquvi_demuxer_deps="libquvi"
1977 1977
 libschroedinger_decoder_deps="libschroedinger"
1978 1978
 libschroedinger_encoder_deps="libschroedinger"
1979
+libshine_encoder_deps="libshine"
1980
+libshine_encoder_select="audio_frame_queue"
1979 1981
 libspeex_decoder_deps="libspeex"
1980 1982
 libspeex_encoder_deps="libspeex"
1981 1983
 libspeex_encoder_select="audio_frame_queue"
... ...
@@ -3997,6 +4001,7 @@ enabled libpulse && require_pkg_config libpulse-simple pulse/simple.h pa_simple_
3997 3997
 enabled libquvi    && require_pkg_config libquvi quvi/quvi.h quvi_init
3998 3998
 enabled librtmp    && require_pkg_config librtmp librtmp/rtmp.h RTMP_Socket
3999 3999
 enabled libschroedinger && require_pkg_config schroedinger-1.0 schroedinger/schro.h schro_init
4000
+enabled libshine   && require_pkg_config shine shine/layer3.h shine_encode_frame
4000 4001
 enabled libsoxr    && require  libsoxr soxr.h soxr_create -lsoxr
4001 4002
 enabled libspeex   && require  libspeex speex/speex.h speex_decoder_init -lspeex
4002 4003
 enabled libstagefright_h264  && require_cpp libstagefright_h264 "binder/ProcessState.h media/stagefright/MetaData.h
... ...
@@ -4398,6 +4403,7 @@ echo "threading support         ${thread_type-no}"
4398 4398
 echo "safe bitstream reader     ${safe_bitstream_reader-no}"
4399 4399
 echo "SDL support               ${sdl-no}"
4400 4400
 echo "opencl enabled            ${opencl-no}"
4401
+echo "libshine enabled          ${libshine-no}"
4401 4402
 echo "texi2html enabled         ${texi2html-no}"
4402 4403
 echo "perl enabled              ${perl-no}"
4403 4404
 echo "pod2man enabled           ${pod2man-no}"
... ...
@@ -687,6 +687,7 @@ OBJS-$(CONFIG_LIBSCHROEDINGER_DECODER)    += libschroedingerdec.o \
687 687
                                              libschroedinger.o
688 688
 OBJS-$(CONFIG_LIBSCHROEDINGER_ENCODER)    += libschroedingerenc.o \
689 689
                                              libschroedinger.o
690
+OBJS-$(CONFIG_LIBSHINE_ENCODER)           += libshine.o
690 691
 OBJS-$(CONFIG_LIBSPEEX_DECODER)           += libspeexdec.o
691 692
 OBJS-$(CONFIG_LIBSPEEX_ENCODER)           += libspeexenc.o
692 693
 OBJS-$(CONFIG_LIBSTAGEFRIGHT_H264_DECODER)+= libstagefright.o
... ...
@@ -482,6 +482,7 @@ void avcodec_register_all(void)
482 482
     REGISTER_ENCDEC (LIBOPENJPEG,       libopenjpeg);
483 483
     REGISTER_ENCDEC (LIBOPUS,           libopus);
484 484
     REGISTER_ENCDEC (LIBSCHROEDINGER,   libschroedinger);
485
+    REGISTER_ENCODER(LIBSHINE,          libshine);
485 486
     REGISTER_ENCDEC (LIBSPEEX,          libspeex);
486 487
     REGISTER_DECODER(LIBSTAGEFRIGHT_H264, libstagefright_h264);
487 488
     REGISTER_ENCODER(LIBTHEORA,         libtheora);
488 489
new file mode 100644
... ...
@@ -0,0 +1,149 @@
0
+/*
1
+ * Interface to libshine for mp3 encoding
2
+ * Copyright (c) 2012 Paul B Mahol
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+#include <shine/layer3.h>
22
+
23
+#include "libavutil/intreadwrite.h"
24
+#include "audio_frame_queue.h"
25
+#include "avcodec.h"
26
+#include "internal.h"
27
+#include "mpegaudio.h"
28
+#include "mpegaudiodecheader.h"
29
+
30
+#define BUFFER_SIZE (4096 * 20)
31
+
32
+typedef struct SHINEContext {
33
+    shine_config_t  config;
34
+    shine_t         shine;
35
+    uint8_t         buffer[BUFFER_SIZE];
36
+    int             buffer_index;
37
+    AudioFrameQueue afq;
38
+} SHINEContext;
39
+
40
+static av_cold int libshine_encode_init(AVCodecContext *avctx)
41
+{
42
+    SHINEContext *s = avctx->priv_data;
43
+
44
+    if (avctx->channels <= 0 || avctx->channels > 2){
45
+        av_log(avctx, AV_LOG_ERROR, "only mono or stereo is supported\n");
46
+        return AVERROR(EINVAL);
47
+    }
48
+
49
+    shine_set_config_mpeg_defaults(&s->config.mpeg);
50
+    if (avctx->bit_rate)
51
+        s->config.mpeg.bitr = avctx->bit_rate / 1000;
52
+    if (shine_find_bitrate_index(s->config.mpeg.bitr) < 0) {
53
+        av_log(avctx, AV_LOG_ERROR, "invalid bitrate\n");
54
+        return AVERROR(EINVAL);
55
+    }
56
+    s->config.mpeg.mode = avctx->channels == 2 ? STEREO : MONO;
57
+    s->config.wave.samplerate = avctx->sample_rate;
58
+    s->config.wave.channels   = avctx->channels == 2 ? PCM_STEREO : PCM_MONO;
59
+    s->shine = shine_initialise(&s->config);
60
+    if (!s->shine)
61
+        return AVERROR(ENOMEM);
62
+    avctx->frame_size = samp_per_frame;
63
+    ff_af_queue_init(avctx, &s->afq);
64
+    return 0;
65
+}
66
+
67
+static int libshine_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
68
+                                 const AVFrame *frame, int *got_packet_ptr)
69
+{
70
+    SHINEContext *s = avctx->priv_data;
71
+    MPADecodeHeader hdr;
72
+    unsigned char *data;
73
+    long written;
74
+    int ret, len;
75
+
76
+    if (frame)
77
+        data = shine_encode_frame(s->shine, frame->data[0], &written);
78
+    else
79
+        data = shine_flush(s->shine, &written);
80
+    if (written < 0)
81
+        return -1;
82
+    if (written > 0) {
83
+        if (s->buffer_index + written > BUFFER_SIZE) {
84
+            av_log(avctx, AV_LOG_ERROR, "internal buffer too small\n");
85
+            return AVERROR_BUG;
86
+        }
87
+        memcpy(s->buffer + s->buffer_index, data, written);
88
+        s->buffer_index += written;
89
+    }
90
+    if (frame) {
91
+        if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
92
+            return ret;
93
+    }
94
+
95
+    if (s->buffer_index < 4 || !s->afq.frame_count)
96
+        return 0;
97
+    if (avpriv_mpegaudio_decode_header(&hdr, AV_RB32(s->buffer))) {
98
+        av_log(avctx, AV_LOG_ERROR, "free format output not supported\n");
99
+        return -1;
100
+    }
101
+
102
+    len = hdr.frame_size;
103
+    if (len <= s->buffer_index) {
104
+        if ((ret = ff_alloc_packet2(avctx, avpkt, len)))
105
+            return ret;
106
+        memcpy(avpkt->data, s->buffer, len);
107
+        s->buffer_index -= len;
108
+        memmove(s->buffer, s->buffer + len, s->buffer_index);
109
+
110
+        ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
111
+                           &avpkt->duration);
112
+
113
+        avpkt->size = len;
114
+        *got_packet_ptr = 1;
115
+    }
116
+    return 0;
117
+}
118
+
119
+static av_cold int libshine_encode_close(AVCodecContext *avctx)
120
+{
121
+    SHINEContext *s = avctx->priv_data;
122
+
123
+    ff_af_queue_close(&s->afq);
124
+    shine_close(s->shine);
125
+    return 0;
126
+}
127
+
128
+static const int libshine_sample_rates[] = {
129
+    44100, 48000, 32000, 0
130
+};
131
+
132
+AVCodec ff_libshine_encoder = {
133
+    .name                  = "libshine",
134
+    .type                  = AVMEDIA_TYPE_AUDIO,
135
+    .id                    = CODEC_ID_MP3,
136
+    .priv_data_size        = sizeof(SHINEContext),
137
+    .init                  = libshine_encode_init,
138
+    .encode2               = libshine_encode_frame,
139
+    .close                 = libshine_encode_close,
140
+    .capabilities          = CODEC_CAP_DELAY,
141
+    .sample_fmts           = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16P,
142
+                                                            AV_SAMPLE_FMT_NONE },
143
+    .supported_samplerates = libshine_sample_rates,
144
+    .channel_layouts       = (const uint64_t[]) { AV_CH_LAYOUT_MONO,
145
+                                                  AV_CH_LAYOUT_STEREO,
146
+                                                  0 },
147
+    .long_name             = NULL_IF_CONFIG_SMALL("libshine MP3 (MPEG audio layer 3)"),
148
+};