Hassan Adeel wrote:
> hi, benjamin,
>
> i think you were talking about this page
>
> http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2007-February/024071.html
>
> but....
> 1) which attachment he talking about. If( ffmpeg_diff.obj) thenhow to get
> qcelp folder from it.
> 2) cannot understand step No 3...briefly describe it.
>
Ok, It was abit tricky. Just follow these instructions and you should be
fine.
1. Do a ffmpeg fresh checkout.
2. Apply the patch.
3. Place the ref decoder in /libavcodec/qcelp (get it from
http://article.gmane.org/gmane.comp.video.ffmpeg.devel/45295/match=vidhya+mani
or 3gpp2's site)
4. Compile ffmpeg
5. Cry coz it doesn't work
6. Complain on the users list coz it didn't work
Oh and this patch wont be push into svn. And distributing ffmpeg
versions with this staticly linked to it is not allowed with the respect
to LGPL license.
MvH
Benjamin Larsson
Index: libavcodec/qcelp.c
===================================================================
--- libavcodec/qcelp.c (revision 0)
+++ libavcodec/qcelp.c (revision 0)
@@ -0,0 +1,302 @@
+/*
+ * QCELP Audio encoder / decoder stub
+ * Copyright (c) 2006 the ffmpeg project
+ *
+ * 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
+ */
+
+/*
+ * The QCELP (Quallcom CELP) codec was originally developed by QUALLCOMM for
+ * its PureVoice(TM) product families and now used by several notable
+ * telecommunication carriers. Eventually adopted by the 3GPP2 committee for
+ * the speech codec with the published specification and the reference
+ * implementation, which this glue code uses for now.
+ *
+ * To enable QCELP codec support,
+ * 1. Download the reference implementation from the the 3GPP2 project page:
+ *
+ *
http://www.3gpp2.org/Public_html/specs/alltsgscfm.cfm
+ *
+ * The file in question is entitled as follows:
+ *
+ * C.R0020-A v1.0 Software Distribution for High Rate Speech (13k),
+ * Service Option 17, Specification (228KB)
+ *
+ * 2. Extract the files to libavcodec/qcelp so the directory structure
+ * would be organized in the following layout:
+ *
+ * libavcodec/
+ * +- qcelp/
+ * +- code/
+ * +- dsp_fx/
+ * +- fxptlibs/
+ * +- tty/
+ * +- ttylib.45/
+ *
+ * 3. Patch the RI source.
+ *
+ * Because the RI source shares the same pieces as the AMR's RI,
+ * (I don't know what happened among them though :) I had bothered
+ * to rewrite some part of the code. You can grab the patch from the
+ * following location:
+ *
+ *
http://voltex.jp/patches/qcelp-conflict-avoidance-patch-20061211.diff.gz
+ *
+ * Enjoy!
+ *
+ * -- moriyoshi
+ */
+
+#include "avcodec.h"
+#include "qcelp/code/celp.h"
+
+#define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
+
+typedef struct QCELPContext {
+ struct CONTROL control;
+ struct ENCODER_MEM encoder;
+ struct DECODER_MEM decoder;
+ float samples[LPCSIZE + LPCOFFSET];
+ float out_buf[FSIZE];
+} QCELPContext;
+
+static const int frame_size_map[16] = {
+ 0, 3, 7, 16, 34, 7, -1, -1,
+ -1, -1, -1, -1, -1, -1, 0, -1,
+};
+
+static int qcelp_decode_init(AVCodecContext *avctx)
+{
+ QCELPContext *s = (QCELPContext *)avctx->priv_data;
+
+ initialize_encoder_and_decoder(&s->encoder, &s->decoder, &s->control);
+ avctx->sample_rate = 8000;
+ avctx->channels = 1;
+
+ return 0;
+}
+
+static int qcelp_decode_frame(AVCodecContext * avctx,
+ void *data, int *data_size,
+ uint8_t * buf, int buf_size)
+{
+ QCELPContext *s = (QCELPContext *)avctx->priv_data;
+ const uint8_t *p, *end;
+ short *q;
+ float samples[FSIZE];
+ struct PACKET pkt;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ p = buf;
+ q = (short *)data;
+
+ for (end = buf + buf_size; p < end; ) {
+ int i, noctets;
+ const uint8_t *lim;
+
+ noctets = frame_size_map[(pkt.data[0] = *p++) & 0x0f];
+ if (noctets < 0) {
+ av_log(avctx, AV_LOG_ERROR, "decoder error (%d)\n", pkt.data[0]);
+ return -1;
+ }
+
+ if (p + noctets > end) {
+ break;
+ }
+
+ for (i = 0, lim = p + (noctets & ~1); p < lim; p += 2) {
+ pkt.data[++i] = BE_16(p);
+ }
+
+ if ((noctets & 1)) {
+ pkt.data[++i] = *p++;
+ }
+
+ decoder(samples, &pkt, &s->control, &s->decoder);
+
+ for (i = 0; i < FSIZE; i++) {
+ *q++ = FFMIN(32768, FFMAX(-32768, samples[i] * 4));
+ }
+ }
+
+ if (p - buf < buf_size) {
+ av_log(avctx, AV_LOG_ERROR, "OOPS %d %d\n", p - buf, buf_size);
+ return -1;
+ }
+
+ *data_size = (uint8_t*)q - (uint8_t*)data;
+ avctx->frame_size = p - buf;
+
+ return p - buf;
+}
+
+static int qcelp_decode_close(AVCodecContext *avctx)
+{
+ QCELPContext *s = (QCELPContext *)avctx->priv_data;
+
+ free_encoder_and_decoder(&s->encoder, &s->decoder);
+ return 0;
+}
+
+static int qcelp_encode_init(AVCodecContext *avctx)
+{
+ QCELPContext *s = (QCELPContext *)avctx->priv_data;
+ static int rate_frac_map[] = {
+ FULLRATE_VOICED,
+ HALFRATE_VOICED,
+ QUARTERRATE_VOICED,
+ QUARTERRATE_VOICED,
+ EIGHTH
+ };
+
+ int rate_frac;
+
+ if (avctx->sample_rate != 8000) {
+ av_log(avctx, AV_LOG_ERROR, "Only 8000Hz sample rate supported\n");
+ return -1;
+ }
+
+ if (avctx->channels != 1) {
+ av_log(avctx, AV_LOG_ERROR, "Only mono channel supported\n");
+ return -1;
+ }
+
+ rate_frac = (16000 - 1) / avctx->bit_rate;
+ if (rate_frac > 4) {
+ rate_frac = 4;
+ }
+
+ initialize_encoder_and_decoder(&s->encoder, &s->decoder, &s->control);
+ s->control.min_rate = EIGHTH;
+ s->control.max_rate = rate_frac_map[rate_frac];
+ s->control.avg_rate = 9.0;
+ s->control.target_snr_thr = 10.0;
+ s->control.pf_flag = PF_ON;
+ s->control.cb_out = NO;
+ s->control.pitch_out = NO;
+ s->control.print_packets = NO;
+ s->control.output_encoder_speech = NO;
+ s->control.form_res_out = NO;
+ s->control.reduced_rate_flag = NO;
+ s->control.unvoiced_off = YES;
+ s->control.pitch_post = YES;
+ s->control.per_wght = PERCEPT_WGHT_FACTOR;
+ s->control.target_after_out = NO;
+ s->control.fractional_pitch = YES;
+ avctx->extradata_size = 0;
+ avctx->frame_size = FSIZE * 10; /* hmm.. */
+ avctx->coded_frame = avcodec_alloc_frame();
+ avctx->coded_frame->key_frame = 1;
+
+ return 0;
+}
+
+static int qcelp_encode_frame(AVCodecContext * avctx,
+ uint8_t *buf, int buf_size, void *data)
+{
+ QCELPContext *s = (QCELPContext *)avctx->priv_data;
+ uint8_t *p;
+ const short *q, *end;
+ struct PACKET pkt;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ q = (const short *)data;
+ p = buf;
+
+ for (end = q + avctx->frame_size; q < end; ) {
+ int i;
+ uint8_t *lim;
+ int noctets;
+
+ i = LPCSIZE - FSIZE + LPCOFFSET;
+ while (q < end && i < LPCSIZE + LPCOFFSET) {
+ s->samples[i++] = (float)(*q++) / 4;
+ }
+
+ while (i < LPCSIZE + LPCOFFSET) {
+ s->samples[i++] = 0;
+ }
+
+ encoder(s->samples, &pkt, &s->control, &s->encoder, s->out_buf);
+
+ update_snr(ENCODER, s->samples, s->out_buf, &s->control.snr);
+
+ noctets = frame_size_map[pkt.data[0] & 0x0f];
+ if (noctets < 0) {
+ av_log(avctx, AV_LOG_ERROR, "encoder error (%d)\n", pkt.data[0]);
+ return -1;
+ }
+
+ *p++ = pkt.data[0];
+
+ for (i = 1, lim = p + (noctets & ~1); p < lim; i++) {
+ *p++ = (pkt.data[i] >> 8) & 0xff;
+ *p++ = pkt.data[i] & 0xff;
+ }
+
+ if ((noctets & 1)) {
+ *p++ = pkt.data[i] & 0xff;
+ }
+
+ memmove(s->samples, s->samples + FSIZE,
+ sizeof(s->samples[0]) * (LPCSIZE - FSIZE + LPCOFFSET));
+
+ s->encoder.frame_num++;
+ }
+
+ return p - buf;
+}
+
+static int qcelp_encode_close(AVCodecContext *avctx)
+{
+ QCELPContext *s = (QCELPContext *)avctx->priv_data;
+
+ free_encoder_and_decoder(&s->encoder, &s->decoder);
+ av_freep(&avctx->coded_frame);
+ return 0;
+}
+
+
+AVCodec qcelp_decoder =
+{
+ "qcelp",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_QCELP,
+ sizeof(QCELPContext),
+ qcelp_decode_init,
+ NULL,
+ qcelp_decode_close,
+ qcelp_decode_frame,
+};
+
+AVCodec qcelp_encoder =
+{
+ "qcelp",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_QCELP,
+ sizeof(QCELPContext),
+ qcelp_encode_init,
+ qcelp_encode_frame,
+ qcelp_encode_close,
+ NULL,
+};
+
+/*
+ * vim: sts=4 sw=4 ts=4 et
+ ,*/
Index: libavcodec/Makefile
===================================================================
--- libavcodec/Makefile (revision 9723)
+++ libavcodec/Makefile (working copy)
@@ -28,9 +28,60 @@
bitstream_filter.o \
audioconvert.o \
+ifeq ($(CONFIG_QCELP),yes)
+CFLAGS += -Iqcelp/code -Iqcelp/tty -Iqcelp/dsp_fx -Iqcelp/fxptlibs
+endif
-HEADERS = avcodec.h opt.h
+OBJS-$(CONFIG_QCELP_DECODER) += qcelp.o
+OBJS-$(CONFIG_QCELP_DECODER) += \
+ qcelp/tty/dit2a.o \
+ qcelp/tty/tty_char.o \
+ qcelp/tty/tty_glob.o \
+ qcelp/tty/ttystate.o \
+ qcelp/tty/tty_rate.o \
+ qcelp/tty/tone_gen.o \
+ qcelp/tty/bdo2dit.o \
+ qcelp/tty/tty_bit.o \
+ qcelp/tty/tty_dbg.o \
+ qcelp/tty/tty_dec.o \
+ qcelp/tty/tty_enc.o \
+ qcelp/tty/tty_gen.o \
+ qcelp/tty/tty_hdr.o \
+ qcelp/code/cb.o \
+ qcelp/code/io.o \
+ qcelp/code/quantabs.o \
+ qcelp/code/quantize.o \
+ qcelp/code/lsp.o \
+ qcelp/code/snr.o \
+ qcelp/code/ratedec.o \
+ qcelp/code/filter.o \
+ qcelp/code/encode.o \
+ qcelp/code/coderate.o \
+ qcelp/code/cb_tabs.o \
+ qcelp/code/fer_sim.o \
+ qcelp/code/decode.o \
+ qcelp/code/init.o \
+ qcelp/code/pack.o \
+ qcelp/code/hammtab.o \
+ qcelp/code/log_10.o \
+ qcelp/code/lpc.o \
+ qcelp/code/target.o \
+ qcelp/code/postfilt.o \
+ qcelp/code/pitch.o \
+ qcelp/code/frontfil.o \
+ qcelp/code/modetabs.o \
+ qcelp/dsp_fx/basic_op40.o \
+ qcelp/dsp_fx/lib_wmp_fx.o \
+ qcelp/dsp_fx/math_ext32.o \
+ qcelp/dsp_fx/math_ext40.o \
+ qcelp/dsp_fx/basic_op.o \
+ qcelp/dsp_fx/math_adv40.o \
+ qcelp/dsp_fx/math_adv.o \
+ qcelp/fxptlibs/ops/ops.o
+
+HEADERS += avcodec.h opt.h
+
OBJS-$(CONFIG_AASC_DECODER) += aasc.o
OBJS-$(CONFIG_AC3_ENCODER) += ac3enc.o ac3tab.o ac3.o
OBJS-$(CONFIG_ALAC_DECODER) += alac.o
Index: libavcodec/allcodecs.c
===================================================================
--- libavcodec/allcodecs.c (revision 9723)
+++ libavcodec/allcodecs.c (working copy)
@@ -120,6 +120,7 @@
REGISTER_ENCDEC (PNG, png);
REGISTER_ENCODER(PPM, ppm);
REGISTER_DECODER(PTX, ptx);
+ REGISTER_ENCDEC (QCELP, qcelp);
REGISTER_DECODER(QDRAW, qdraw);
REGISTER_DECODER(QPEG, qpeg);
REGISTER_ENCDEC (QTRLE, qtrle);
Index: libavcodec/allcodecs.h
===================================================================
--- libavcodec/allcodecs.h (revision 9723)
+++ libavcodec/allcodecs.h (working copy)
@@ -56,6 +56,8 @@
extern AVCodec pgmyuv_encoder;
extern AVCodec png_encoder;
extern AVCodec ppm_encoder;
+extern AVCodec qcelp_encoder;
+extern AVCodec qcelp_decoder;
extern AVCodec qtrle_encoder;
extern AVCodec roq_dpcm_encoder;
extern AVCodec roq_encoder;
Index: doc/ffmpeg-doc.texi
===================================================================
--- doc/ffmpeg-doc.texi (revision 9723)
+++ doc/ffmpeg-doc.texi (working copy)
@@ -1121,6 +1121,8 @@
@tab Supported through an external library.
@item AMR-WB @tab X @tab X
@tab Supported through an external library.
+@item QCELP @tab X @tab X
+@tab Supported through an external library.
@item DV audio @tab @tab X
@item Id RoQ DPCM @tab X @tab X
@tab Used in Quake III, Jedi Knight 2, other computer games.
Index: libavformat/mov.c
===================================================================
--- libavformat/mov.c (revision 9723)
+++ libavformat/mov.c (working copy)
@@ -836,6 +836,10 @@
st->codec->sample_rate= 8000;
st->codec->channels= 1; /* really needed */
break;
+ case CODEC_ID_QCELP:
+ st->codec->sample_rate = 8000;
+ st->codec->channels = 1;
+ break;
case CODEC_ID_MP2:
case CODEC_ID_MP3:
st->codec->codec_type = CODEC_TYPE_AUDIO; /* force type after stsd for m1a hdlr */
Index: libavformat/movenc.c
===================================================================
--- libavformat/movenc.c (revision 9723)
+++ libavformat/movenc.c (working copy)
@@ -372,7 +372,8 @@
track->enc->codec_id == CODEC_ID_PCM_S24LE ||
track->enc->codec_id == CODEC_ID_PCM_S32LE))
mov_write_wave_tag(pb, track);
- else if(track->enc->codec_id == CODEC_ID_AAC)
+ else if(track->enc->codec_id == CODEC_ID_AAC ||
+ track->enc->codec_id == CODEC_ID_QCELP)
mov_write_esds_tag(pb, track);
else if(track->enc->codec_id == CODEC_ID_AMR_NB)
mov_write_amr_tag(pb, track);
_______________________________________________
ffmpeg-user mailing list
ffmpeg-user@???
http://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-user